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 |