今天来讲矩阵加速:
例题:https://www.luogu.org/problemnew/show/P1939
如果一个个去求就会T掉,所以我们使用矩阵加速。
矩阵加速是用来解决一些与递推式有关的问题,形如f(x)=a(x)p1+a(x-1)p2+……+a(x-k)pk(已知几个初项)
我们可以建立一个矩阵:
这个时候,我们发现中间那一个数字组成的矩阵会重复多次计算,这个过程可以用矩阵快速幂解决。
因此,对于,我们可以:
用快速幂解决中间部分,最后与初项相乘,可得到an。
这个推理的部分,可以尝试在纸上解决。
上代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 ll n,num,answer; 5 const ll mod=1e9+7; 6 struct matrix{ 7 ll a[5][5]; 8 void Empty(){ 9 memset(a,0,sizeof(a)); 10 } 11 void One(){ 12 Empty(); 13 for(int i=1;i<=3;i++) a[i][i]=1; 14 } 15 void reset(){ 16 Empty(); 17 a[1][1]=a[1][3]=a[2][1]=a[3][2]=1; 18 } 19 matrix operator*(matrix b){ 20 matrix tmp; 21 tmp.Empty(); 22 for(int i=1;i<=3;i++){ 23 for(int j=1;j<=3;j++){ 24 for(int k=1;k<=3;k++){ 25 (tmp.a[i][j]+=a[i][k]*b.a[k][j]%mod)%=mod; 26 } 27 } 28 } 29 return tmp; 30 } 31 }res,ans; 32 void pow(ll p){ 33 res.reset(); 34 ans.One(); 35 while(p){ 36 if(p&1){ 37 ans=ans*res; 38 } 39 res=res*res; 40 p>>=1; 41 } 42 } 43 int main(){ 44 cin>>n; 45 for(int i=1;i<=n;i++){ 46 cin>>num; 47 if(num<4){ 48 cout<<1<<endl; 49 continue; 50 } 51 pow(num-3); 52 answer=(ans.a[1][1]%mod+ans.a[2][1]%mod+ans.a[3][1]%mod)%mod; 53 cout<<answer<<endl; 54 } 55 return 0; 56 }