https://www.acmicpc.net/problem/11444

 

피보나치 수를 분할정복 방식으로 풀어야하는 문제이다. 

이때 행렬 분할 정복 방식을 사용해보자 

 

피보나치 수는 위와 같이 행렬의 곱셈을 통해 표현할 수 있다. 그렇게 때문에 피보나치의 기본 수 부터  n-1 번째 행렬의 거듭제곱을 계산해주면 n번째 피보나치 수를 빠르게 구할 수 있다. 

즉 n-1까지의 거듭제곱을 계산해주고 이 행렬의 0,0위치 의 값을 반환해주면 n번째 피보나치 수를 구할 수 있다.

 

정답코드

#include <iostream>
#include <vector>
#define MOD 1000000007

using namespace std;

typedef vector<vector<long long>> Matrix;

//행렬 곱셈 함수
Matrix multiply(const Matrix& a, const Matrix& b)
{
	//곱셈 결과를 저장할 함수
	Matrix result(2, vector<long long>(2, 0));
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 2; j++)
		{
			for (int k = 0; k < 2; k++)
			{
				result[i][j] = (result[i][j] + a[i][k] * b[k][j]) % MOD;
			}
		}
	}

	return result;
}

//행렬 거듭제곱 함수
Matrix matrixPower(Matrix a, long long n) {
	Matrix result = { {1, 0}, {0, 1} }; // 단위 행렬
	while (n > 0) {
		if (n % 2 == 1) {
			result = multiply(result, a);
		}
		a = multiply(a, a);
		n /= 2;
	}
	return result;
}

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

	if (n == 0) {
		cout << 0 << endl;
		return 0;
	}

	// 피보나치 초기 행렬
	Matrix a = { {1, 1}, {1, 0} };

	//n번째까지의 피노나치 계산
	Matrix result = matrixPower(a, n - 1);
	
	cout << result[0][0] << "\n";

	return 0;
}

'코딩테스트 > 백준' 카테고리의 다른 글

[백준][C++]2559번. 수열  (0) 2024.11.18
[백준][C++]11659번. 구간 합 구하기4  (0) 2024.11.17
[백준][C++]10830번. 행렬 제곱  (0) 2024.11.15
[백준][C++]1629번. 곱셈  (0) 2024.11.14
[백준][C++]2740번. 행렬 곱셈  (0) 2024.11.13

+ Recent posts