斐波那契数列定义:F0=0;F1=1;Fn+2=Fn+1 +Fn;其中0<=n<=10^16,最后结果对m=10000007取模。
对于较小的n直接通过定义式递归求解就可,但是对于较大的n时,直接递归算法效率极低,当然也可以直接用埃氏筛法来打表,但是当n再大点,达到10^16的级别,就无法开这么大的数组了。那规模如此之大的问题该如何求解呢?
可能也有人会想到递推式代入求解,下面就是斐波那契通项公式:
其中公式中包含了无理数,无法简单地直接精确求出结果。所以对于这么大的数据,用矩阵则可以高效地求解出第n项值。
首先,对于斐波那契的定义式我们可以变换成矩阵,即:
,其中,记A=
所以就可以得出一下递推关系矩阵:
因此,只要求出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;
}