1. 程式人生 > >斐波那契數列——矩陣的冪求解

斐波那契數列——矩陣的冪求解

題目:

斐波那契數列的遞推公式如下:

F(0) = 0;

F(1) = 1;

F(n + 2) = F(n + 1) + F(n);

求數列的第N項的值對10000取餘的結果。( 0<=n<= 10^16)

求解斐波那契數列,如果N比較小的情況下,可以直接打表求解,但是對於N很大的情況下,並不適用。

所以,有些人會想到高精度計算,但是,N達到10^5以上時,時間複雜度難以想象,每計算一個數,需要進行高精度加法。然而還有求解對10000的取餘的值。

我們可以用矩陣的冪來求解。斐波那契數列的遞推公式為F(n + 2) = F(n + 1) + F(n);可以轉換為矩陣的形式


將這公式乘開,還是等於上面的遞推公式。因此,得到了F(n)的求解公式



下面的是程式碼:

#include <iostream>
#include <vector>
using namespace std;

typedef vector<int> vec;
typedef vector<vec> mat;
typedef __int64 ll;

const int M = 10000;

mat mul(mat &A, mat &B)    //矩陣相乘函式
{
	mat C(A.size(), vec(B.size()));  //二維陣列
	for(int i = 0; i < A.size(); i++)
		for(int k = 0; k < B.size(); k++)
			for(int j = 0; j < B.size(); j++)
				C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % M;
	return C;
}

mat pows(mat A, ll n)        //快速冪運算
{
	mat B(A.size(), vec(A.size()));  //二維陣列
	for(int i = 0; i < A.size(); i++)
		B[i][i] = 1;
	while(n > 0)
	{
		if(n & 1)
			B = mul(B, A);
		A = mul(A, A);
		n >>= 1;
	}
	return B;
}

int main()
{
	ll n;
	while(scanf("%I64d", &n) != EOF) //輸入n
	{
		mat A(2, vec(2));
		A[0][0] = 1; A[0][1] = 1;
		A[1][0] = 1; A[1][1] = 0;
		A = pows(A, n);
		printf("%d\n", A[1][0]);
	}
	return 0;
}