斐波那契数列定义:F0=0;F1=1;Fn+2=Fn+1 +Fn;其中0<=n<=10^16,最后结果对m=10000007取模。

对于较小的n直接通过定义式递归求解就可,但是对于较大的n时,直接递归算法效率极低,当然也可以直接用埃氏筛法来打表,但是当n再大点,达到10^16的级别,就无法开这么大的数组了。那规模如此之大的问题该如何求解呢?

可能也有人会想到递推式代入求解,下面就是斐波那契通项公式:

                                                           

矩阵幂——斐波那契数列_斐波那契

其中公式中包含了无理数,无法简单地直接精确求出结果。所以对于这么大的数据,用矩阵则可以高效地求解出第n项值。

首先,对于斐波那契的定义式我们可以变换成矩阵,即:

                                                 

矩阵幂——斐波那契数列_#include_02

,其中,记A=

矩阵幂——斐波那契数列_矩阵快速幂_03

所以就可以得出一下递推关系矩阵:

矩阵幂——斐波那契数列_矩阵快速幂_04

因此,只要求出A^n就可以求出Fn,而对于A^n,可以根据快速幂运算,在O(log(n))的时间内求解出来第n项的值。

#include<cstdio>
#include<vector>
using namespace std;
typedef vector<int> vec;
typedef vector<vec> mat;
int m=10000007;
mat mul(mat a,mat b) {//矩阵运算
	mat c(a.size(),vec(a.size()));
	for(int i=0; i<a.size(); ++i)
		for(int k=0; k<b.size(); ++k)
			for(int j=0; j<b[0].size(); ++j) {
				c[i][j]=(c[i][j]+a[i][k]*b[k][j])%m;
			}
	return c;
}
mat pow(mat a,int 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() {
	int n;
	scanf("%d",&n);
	mat a(2,vec(2));
    //矩阵初始化
	a[0][0]=1;
	a[0][1]=1;
	a[1][0]=1;
	a[1][1]=0;
	a=pow(a,n);
	printf("%d\n",a[1][0]);
	return 0;
}