1 minute read

백준 문제 중 1003번

https://www.acmicpc.net/problem/1003

문제

다음 소스는 N번째 피보나치 수를 구하는 C++ 함수이다.

int fibonacci(int n) {
    if (n == 0) {
        printf("0");
        return 0;
    } else if (n == 1) {
        printf("1");
        return 1;
    } else {
        return fibonacci(n1) + fibonacci(n2);
    }
}

fibonacci(3)을 호출하면 다음과 같은 일이 일어난다.

  • fibonacci(3)은 fibonacci(2)와 fibonacci(1) (첫 번째 호출)을 호출한다.
  • fibonacci(2)는 fibonacci(1) (두 번째 호출)과 fibonacci(0)을 호출한다.
  • 두 번째 호출한 fibonacci(1)은 1을 출력하고 1을 리턴한다.
  • fibonacci(0)은 0을 출력하고, 0을 리턴한다.
  • fibonacci(2)는 fibonacci(1)과 fibonacci(0)의 결과를 얻고, 1을 리턴한다.
  • 첫 번째 호출한 fibonacci(1)은 1을 출력하고, 1을 리턴한다.
  • fibonacci(3)은 fibonacci(2)와 fibonacci(1)의 결과를 얻고, 2를 리턴한다.

1은 2번 출력되고, 0은 1번 출력된다. N이 주어졌을 때, fibonacci(N)을 호출했을 때, 0과 1이 각각 몇 번 출력되는지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다.

각 테스트 케이스는 한 줄로 이루어져 있고, N이 주어진다. N은 40보다 작거나 같은 자연수 또는 0이다.

출력

각 테스트 케이스마다 0이 출력되는 횟수와 1이 출력되는 횟수를 공백으로 구분해서 출력한다.


풀이

N 이 40보다 작거나 같은 자연수 또는 0이라는 조건을 활용하면 쉽게 풀 수 있는 문제였다.

문제에서 주어진 재귀 함수로 구현된 피보나치 함수의 동작을 잘 생각해보면 결국 n이 0이나 1로 줄어들때까지 작아진다가 0이나 1이 되면 리턴을하고 그 리턴된 값으로 계산을 시작하는 것이다.
결론적으로 1이나 0의 개수를 구하는 것이나, 피보나치의 수열의 수를 구하는것이나 별로 다를게 없다는 것을 알 수 있다.
단 주의해야 할 점은 피보나치 수열 fibo(0), fibo(1)이 1로 시작하는 반면에 0과 1의 개수는 n = 0 일때 0은 1개 1은 0개 , n = 1 일때 1은 1개 0은 0개로 시작한다는 것이다.

dp[i][0] 는 0의개수 dp[i][1]은 1의개수 dp[i][2] 는 피보나치를 나타낼 수 있는 배열을 0 ~ 40 즉 41개크기만큼으로 선언한다.

그 후 0 ~ 41 까지 모든 경우의 수를 계산한다.

from typing import List

 # dp[0] 는 0의개수 dp[1]은 1의개수 dp[2] 는 피보나치 수
dp = [[0, 0, 0] for _ in range(41)]
dp[0] = [1,0,1]
dp[1] = [0,1,1]

 # 주어질 수 있는 모든 수에 대해 계산
for i in range(2,41):
    dp[i][0] = dp[i-1][0] + dp[i-2][0]
    dp[i][1] = dp[i-1][1] + dp[i-2][1]
    dp[i][2] = dp[i-1][2] + dp[i-2][2]


t = int(input())
nums = []

for _ in range(t):
    nums.append(int(input()))

for num in nums:
    print(dp[num][0],dp[num][1])
2
6
22
5 8
10946 17711

Leave a comment