矩阵加速
题目来源:P1939 【模板】矩阵加速(数列)
其实这道题该是一眼丁真递推的,但貌似没这么简单
看数据量就知道直接递推肯定会超时的O(n)
有什么办法能降低时间复杂度呢?我们可以用到快速幂的思路
不难看出
[a[x], a[x-1], a[x-2]]=[a[x-1], a[x-2], a[x-3]] * A(矩阵)
经过推理可以把A计算出来,然后可得
[a[x], a[x-1], a[x-2]]=[1,1,1]*A^(x-3);
就把问题转化为求A的(n-3)次幂,直接用矩阵快速幂就行
A为
1 1 0
0 0 1
1 0 0
struct matrix{long long m[N][N];};
matrix operator * (const matrix &m1,const matrix &m2){
matrix t;
memset(t.m,0,sizeof(t.m));
for(int i=1;i<N;++i)
for(int j=1;j<N;++j)
for(int k=1;k<N;++k)
t.m[i][j]=(t.m[i][j]+m1.m[i][k]*m2.m[k][j])%mod;
return t;
}
}
matrix fast_pow(matrix x,int y){
matrix res;
memset(res.m,0,sizeof(res.m));
for(int i=1;i<N;++i)
res.m[i][i]=1;
while(y){
if(y&1) res=res * x;
x=x*x;
y>>=1;
}
return res;
}
in
矩阵快速幂代码,和快速幂几乎一模一样
最后附上ac代码
#include<bits/stdc++.h>
using namespace std;
int const N=4;
long long const mod=1e9+7;
struct matrix{long long m[N][N];};
matrix operator * (const matrix &m1,const matrix &m2){
matrix t;
memset(t.m,0,sizeof(t.m));
for(int i=1;i<N;++i)
for(int j=1;j<N;++j)
for(int k=1;k<N;++k)
t.m[i][j]=(t.m[i][j]+m1.m[i][k]*m2.m[k][j])%mod;
return t;
}
void initial(matrix &x){
x.m[1][1]=1;x.m[1][2]=1;x.m[1][3]=0;
x.m[2][1]=0;x.m[2][2]=0;x.m[2][3]=1;
x.m[3][1]=1;x.m[3][2]=0;x.m[3][3]=0;
}
matrix fast_pow(matrix x,int y){
matrix res;
memset(res.m,0,sizeof(res.m));
for(int i=1;i<N;++i)
res.m[i][i]=1;
while(y){
if(y&1) res=res * x;
x=x*x;
y>>=1;
}
return res;
}
int main(void){
int T;cin>>T;
while(T--){
int n;cin>>n;
matrix A;
initial(A);
long long ans=0;
if(n==1 || n==2 || n==3) ans=1;
else{
A=fast_pow(A,n-3);
ans=(A.m[1][1]+A.m[2][1]+A.m[3][1])%mod;
}
cout<<ans<<endl;
}
return 0;
}
一定要注意矩阵的初始化和单位矩阵初始化噢
欢迎批评指正