SDS ( -> PS)

[2일차] 시간복잡도 C - 2748: 피보나치 수 2

왕방토 2022. 1. 6. 01:32
728x90

브론즈 Ⅰ

 

#include <iostream>
using namespace std;

void mul_matrix(long long F[2][2], long long M[2][2]);
void matrix_power(long long F[2][2], int n);

long long fib(int n) {
	long long F[2][2] = { { 1, 1 }, { 1, 0 } };

	if (n == 0) return 0;

	matrix_power(F, n - 1);
	return F[0][0];
}

void mul_matrix(long long F[2][2], long long M[2][2]) {
	long long x = F[0][0] * M[0][0] +
        F[0][1] * M[1][0];
	long long y = F[0][0] * M[0][1] +
        F[0][1] * M[1][1];
	long long z = F[1][0] * M[0][0] +
        F[1][1] * M[1][0];
	long long w = F[1][0] * M[0][1] +
        F[1][1] * M[1][1];

    F[0][0] = x;
    F[0][1] = y;
    F[1][0] = z;
    F[1][1] = w;
}

//기본 F 행렬의 n제곱 계산
void matrix_power(long long F[2][2], int n) {
	int i;
	long long M[2][2] = { { 1, 1 }, { 1, 0 } };

	for (i = 2; i <= n; i++) {
		mul_matrix(F, M);
	}
}

int main() {
	int N;
	scanf("%d", &N);
	printf("%lld", fib(N));
}

 

피보나치 수열의 점화식을 행렬 곱으로 나타낸 다음

행렬 곱을 계산하여 푸는 문제

 

이거 나중에 행렬곱 하나씩 곱하고있지 말고

그 거듭제곱 빨리 계산하는 방법

거듭제곱의 지수를 2진수로 바꾼다음에

dp로 계산해놓은 캐시에서 골라서 쓰는

그 방법으로 하면 o(logn)될 거 같은데

 

일단 위의 방법은 그냥 dp랑 똑같은 o(n)으로 알고있는데 아닐수도있음 나중에 확인