洛咕
POJ
题意:求出 f(n) mod 1e9+7 的值.\((n<=10^{18})\)
分析:直接线性递推肯定超时.考虑矩阵快速幂加速递推(这是一个在线性递推中很常用的优化方法).考虑我们已知矩阵\(S(i-1)=[S_{n-1},S_{n}]\),想要得到矩阵\(S(i)=[S_n,S_{n+1}]\),根据矩阵乘法的运算法则可手玩出转移矩阵\(T= [\begin{matrix} 0 & 1 \\1 & 1 \end{matrix}]\).
于是我们可以设初值为\(S(0)=[0,1]\),目标为\(S(n)=S(0)*T^n\),可以借助矩阵快速幂来计算.
时间复杂度\(O(8logn)\)
#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline LL read(){
LL s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
const LL mod=1e9+7;
struct matrix{
LL a[2][2];
matrix operator *(matrix b){//重载'*'
matrix c;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
c.a[i][j]=0;
//一定先要初始化
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
c.a[i][j]=(c.a[i][j]+1LL*a[i][k]*b.a[k][j])%mod;
return c;
}
}S,T;
int main(){
S.a[0][0]=0;S.a[0][1]=1;//初始矩阵S
T.a[0][0]=0;T.a[0][1]=1;T.a[1][0]=1;T.a[1][1]=1;//转移矩阵T
LL n=read();//十年oi一场空...
while(n){if(n&1)S=S*T;T=T*T;n>>=1;}
//快速幂,我已经重载'*'为矩阵乘法了
printf("%lld\n",S.a[0][0]%mod);
return 0;
}