luogu 传送门
矩阵乘法快速幂,注意记录过程量;
还有就是如果前面已经算过了,直接赋值就好了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#define LL long long
#define MOD 1000000007
using namespace std;
LL A[4][4]={
0,0,0,0,
0,1,1,0,
0,0,0,1,
0,1,0,0,
};
LL ans[2][4],B[4][4],C[4][4],bak[4][4],a[109];
int T;
struct H{
LL n;int id;
}q[109];
bool cmp(H x,H y){return x.n<y.n;};
void Fast_Pow(LL p)
{
p--;
for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) B[i][j]=C[i][j]=A[i][j];
while(p)
{
if(p%2)//B*C
{
for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) bak[i][j]=B[i][j],B[i][j]=0;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
for(int k=1;k<=3;k++)
B[i][j]=(B[i][j]+bak[i][k]*C[k][j]%MOD)%MOD;
}
//C*C
for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) bak[i][j]=C[i][j],C[i][j]=0;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
for(int k=1;k<=3;k++)
C[i][j]=(C[i][j]+bak[i][k]*bak[k][j]%MOD)%MOD;
p/=2;
}
for(int i=1;i<=3;i++) bak[1][i]=ans[1][i],ans[1][i]=0;
ans[1][1]=(bak[1][1]*B[1][1]%MOD+bak[1][2]*B[2][1]%MOD+bak[1][3]*B[3][1]%MOD)%MOD;
ans[1][2]=(bak[1][1]*B[1][2]%MOD+bak[1][2]*B[2][2]%MOD+bak[1][3]*B[3][2]%MOD)%MOD;
ans[1][3]=(bak[1][1]*B[1][3]%MOD+bak[1][2]*B[2][3]%MOD+bak[1][3]*B[3][3]%MOD)%MOD;
}
int main()
{
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
scanf("%lld",&q[i].n);
q[i].id=i;
}
ans[1][1]=1,ans[1][2]=1,ans[1][3]=1;
sort(q+1,q+T+1,cmp);
for(int i=1;i<=T;i++)
{
LL n=q[i].n;
if(n<=3&&n>=1) {a[q[i].id]=1;continue;}
if(i==1) Fast_Pow(q[1].n-3);
else if(n-q[i-1].n)Fast_Pow(n-q[i-1].n);
a[q[i].id]=ans[1][1];
}
for(int i=1;i<=T;i++) printf("%lld
",a[i]);
return 0;
}