Problem
求斐波那契数列第n项,输出答案模10^9+7的值(n<2^63)
Prepare
(对于学过线代的大佬请跳至Solution)
我们先介绍一下矩阵,我们表现形式就是二维数组。而矩阵相对于二维数组不同的是具有乘法运算。
对于n*m的矩阵a和m*p的矩阵b,表示a*b的矩阵c是n*p的,其中矩阵c的第i行j列的元素满足
举个栗子,如下:
顺便指一下,对于n*n的矩阵,唯一存在这个矩阵a,使得对于任意矩阵b,a*b=b,其中a的主对角线上所有数为1,其他数为0
如果还是看不懂,百度百科
Solution
对于斐波那契数列f(n)满足f(n)=f(n-1)+f(n-2)(废话!)
我们构造矩阵a,使得:
所以,我们可以通过计算a^n来得到答案,诶,这不是也要O(n)时间吗?别忘了还有快速幂(kasumi),和普通整数的求幂大抵相差不了多少。
Code
#include<cstdio>
#include<cstring>
#define MOD 1000000007
using namespace std;
typedef long long LL;
struct Matrix {
int n;
LL a[2][2];
Matrix():n(2){memset(a,0,sizeof(a));}
Matrix operator*(const Matrix& mat){
Matrix res;
for(int i=0;i<n;i++)
for(int j=0;j<mat.n;j++)
for(int k=0;k<n;k++)
res.a[i][j]=(a[i][k]*mat.a[k][j]%MOD+res.a[i][j])%MOD;
return res;
}
Matrix operator=(const Matrix& mat){memcpy(a,mat.a,sizeof(a));}
};
Matrix kasumi(Matrix d,LL k){
Matrix ans;
for(int i=0;i<ans.n;i++) ans.a[i][i]=1;
while(k){
if(k&1) ans=ans*d;
d=d*d;
k>>=1;
}
return ans;
}
int main(){
Matrix d;
LL n;
scanf("%lld",&n);
d.a[0][0]=d.a[0][1]=d.a[1][0]=1;
printf("%lld",kasumi(d,n).a[1][0]);
}