[문제 링크]

 

10826번: 피보나치 수 4

피보나치 수는 0과 1로 시작한다. 0번째 피보나치 수는 0이고, 1번째 피보나치 수는 1이다. 그 다음 2번째 부터는 바로 앞 두 피보나치 수의 합이 된다. 이를 식으로 써보면 Fn = Fn-1 + Fn-2 (n ≥ 2)가

www.acmicpc.net


dp의 메모이제이션 기법을 이용하는 전형적인 피보나치 수열 문제였다.

 

다만, n의 최대가 10000인데, 피보나치 수열은 갈수록 값이 어마어마하게 커지기 때문에 n의 값이 클경우 unsigned long long 자료형에도 담을 수 없을 정도로 커지게 된다.

 

따라서 숫자를 문자열로 표현한 다음, 두 문자열의 합을 구해주는 sum 함수를 구현하여 이와 같은 문제를 해결하였다.


#include <iostream>
#include <algorithm>
#include <string>
using namespace std;

string memo[10001];

string sum(string a, string b) {
	string result;
	int up = 0;

	// 자리수가 다를 경우 뒤에 있는 수가 반드시 자리수가 큼
	while (!b.empty()) {
		if (!a.empty()) {
			int num1 = a.back() - '0';
			int num2 = b.back() - '0';
			a.pop_back();
			b.pop_back();

			int sum = num1 + num2 + up;
			up = 0;

			if (sum >= 10) {
				up = 1;
				sum -= 10;
			}
			result.push_back(sum + '0');
		}
		else {
			int num = b.back() - '0';
			b.pop_back();

			int sum = num + up;
			up = 0;

			if (sum >= 10) {
				up = 1;
				sum -= 10;
			}
			result.push_back(sum + '0');
		}
	}
	if (up == 1)
		result.push_back('1');

	reverse(result.begin(), result.end());

	return result;
}

string bottomUp(int n)
{
	memo[0] = '0', memo[1] = '1';
	
	for (int i = 2; i <= n; i++) {
		memo[i] = sum(memo[i - 2], memo[i - 1]);
	}
	
	return memo[n];
}

int main(void)
{
	int n;
	cin >> n;

	cout << bottomUp(n) << endl;
	
	return 0;
}

10000번째 피보나치 수열은 정말 어마어마한 숫자이다.....

'알고리즘 > BOJ' 카테고리의 다른 글

백준 1939번: 중량제한  (0) 2021.10.22
백준 2458번: 키 순서  (0) 2021.10.21
백준 14226번: 이모티콘  (0) 2021.10.20
백준 5052번: 전화번호 목록  (0) 2021.10.20
백준 17135번: 캐슬 디펜스  (0) 2021.10.18

+ Recent posts