https://www.acmicpc.net/problem/2749
2749번: 피보나치 수 3
첫째 줄에 n이 주어진다. n은 1,000,000,000,000,000,000보다 작거나 같은 자연수이다.
www.acmicpc.net
[ 문제풀이 ]
1. 아래의 식을 바탕으로 $F_{n}$의 값을 구할 수 있습니다.
$\begin{pmatrix}
1 & 1\\
1 & 0\\
\end{pmatrix}^{n} = \begin{bmatrix}
F_{n+1} & F_{n} \\
F_{n} & F_{n-1} \\
\end{bmatrix}$
2. 분할 정복을 활용하여 n이 2의 배수라면 $F_{n} = F_{\frac{n}{2}}\times F_{\frac{n}{2}}$ 아니라면 $F_{n-1}\times F_{1}$을 통해 구해줍니다.
3. 메모이제이션을 활용하여 각각의 $F_{i}$을 1,000,000으로 나눈 나머지 값을 저장합니다.
4. $F_{n}$의 [0, 1] 항을 출력해 줍니다.
[ 소스코드 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #include<iostream> #include<vector> #include<map> #define M 1000000 #define ll long long using namespace std; ll n; vector<vector<ll>> mat = { {1,1},{1,0} }; map<ll, vector<vector<ll>>> m; vector<vector<ll>> mul(vector<vector<ll>> a, vector<vector<ll>> b) { vector<vector<ll>> ret = { {0,0},{0,0} }; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { ret[i][j] = (((a[i][0] % M) * (b[0][j] % M)) % M + ((a[i][1] % M) * (b[1][j] % M)) % M) % M; } } return ret; } vector<vector<ll>> conquer(ll n) { if (m[n].size() != 0) return m[n]; if (n == 1) return mat; if (n == 0) return { {1,0},{0,1} }; if (n % 2 == 0) { return m[n] = mul(conquer(n / 2), conquer(n / 2)); } else { return m[n] = mul(conquer(n - 1), conquer(1)); } } int main() { scanf("%lld", &n); vector<vector<ll>> ans = conquer(n); printf("%d", ans[0][1]); } | cs |
'백준' 카테고리의 다른 글
[ 백준 ] 2668번 - 숫자고르기 (C++) (0) | 2023.04.16 |
---|---|
[ 백준 ] 1253번 - 좋다 (C++) (0) | 2023.04.15 |
[ 백준 ] 2436번 - 공약수 (C++) (0) | 2023.04.13 |
[ 백준 ] 1484번 - 다이어트 (C++) (0) | 2023.04.12 |
[ 백준 ] 20366번 - 같이 눈사람 만들래? (C++) (0) | 2023.04.11 |