PS
[C++] 11444 : 피보나치 수 6
왕방토
2022. 1. 8. 23:39
728x90
골드 Ⅱ
#include <iostream>
#define MOD 1000000007
using namespace std;
long long F[2][2] = { {1,1}, {1,0} };
long long M[2][2] = { {1,1}, {1,0} };
int main() {
long long N;
scanf("%lld", &N);
if (N == 0) {
printf("0");
return 0;
}
N--;
while (N) {
if (N % 2 == 1) {
long long x1 = (F[0][0] * M[0][0]) % MOD + (F[0][1] * M[1][0]) % MOD;
long long y1 = (F[0][0] * M[0][1]) % MOD + (F[0][1] * M[1][1]) % MOD;
long long z1 = (F[1][0] * M[0][0]) % MOD + (F[1][1] * M[1][0]) % MOD;
long long w1 = (F[1][0] * M[0][1]) % MOD + (F[1][1] * M[1][1]) % MOD;
F[0][0] = x1 % MOD;
F[0][1] = y1 % MOD;
F[1][0] = z1 % MOD;
F[1][1] = w1 % MOD;
}
long long x2 = (M[0][0] * M[0][0]) % MOD + (M[0][1] * M[1][0]) % MOD;
long long y2 = (M[0][0] * M[0][1]) % MOD + (M[0][1] * M[1][1]) % MOD;
long long z2 = (M[1][0] * M[0][0]) % MOD + (M[1][1] * M[1][0]) % MOD;
long long w2 = (M[1][0] * M[0][1]) % MOD + (M[1][1] * M[1][1]) % MOD;
M[0][0] = x2 % MOD;
M[0][1] = y2 % MOD;
M[1][0] = z2 % MOD;
M[1][1] = w2 % MOD;
N /= 2;
}
printf("%lld", F[1][0]);
return 0;
}
피보나치의 수 정의 점화식을
행렬곱으로 나타내어서 피보나치 수를 log(N)만에 구하는 방법
근데 이것도 FN을 구한답시고 그냥 행렬곱을 N번 곱하고 있으면 똑같이 O(N)이다.
행렬곱으로 하면 log(N)으로 구할 수 있는 이유는
N거듭제곱을 log(N)으로 구할 수 있는 방법이 있기 때문
아래 참조
x^N 구할 때
O(N) 말고 O(logN)으로 구하는 방법
두 가지 -> 재귀/while문
중 while문 선택했는데 조금 헷갈린다
https://onsil-thegreenhouse.github.io/programming/problem/2018/03/29/problem_math_power/
[Problem] 어떤 수의 n제곱 구하기(백준 1629번) - Onsil's blog
초짜 개발자 온실의<br> 스터디 블로그
onsil-thegreenhouse.github.io