题解 P5303 【[GXOI/GZOI2019]逼死强迫症】
令
考虑最右侧多出了一列,我们可以直接放一个
这是最右边不放
考虑最右侧放了
发现另一个这个方块能放在
然后这个
设
那么有
发现
所以
用矩阵快速幂维护即可。需要维护
时间复杂度
Code:
#include<cstdio>
#include<cstring>
const int md=1e9+7;
typedef long long LL;
struct mat{
int a[5][5];
inline mat(){memset(a,0,sizeof a);}
inline mat operator*(const mat&b)const{
mat c;
for(int i=0;i<5;++i)
for(int k=0;k<5;++k)
for(int j=0;j<5;++j)
c.a[i][j]=(c.a[i][j]+(LL)a[i][k]*b.a[k][j])%md;
return c;
}
}s;
mat pow(mat a,int b){
mat ret;
ret.a[0][0]=ret.a[1][1]=ret.a[2][2]=ret.a[3][3]=ret.a[4][4]=1;
for(;b;b>>=1,a=a*a)
if(b&1)ret=ret*a;
return ret;
}
int main(){
s.a[0][1]=s.a[1][0]=s.a[1][1]=s.a[2][3]=s.a[3][2]=s.a[3][3]=s.a[4][4]=1;
s.a[3][1]=2,s.a[4][1]=md-1;
int T;
for(scanf("%d",&T);T--;){
int n;
scanf("%d",&n);
if(n<3)
puts("0");
else{
mat ans;
ans.a[0][2]=1,ans.a[0][3]=ans.a[0][4]=2;
printf("%d\n",(ans*pow(s,n-2)).a[0][1]);
}
}
return 0;
}