只有两行,考虑递推,设(f_i)为没有那两个(1*1)的,前(i)列的方案,可以发现一次可以放一个竖的或两个横的,也就是(f_i=f_{i-1}+f_{i-2})
再设(g_i)表示有那两个(1*1)的,前(i)列的方案,首先和(f)类似,可以放一个竖的或两个横的(1*2),然后(1*1)可以放出长度为奇数,(ge3)的两种矩形,或者长度为偶数,(ge4)的两种矩形,所以$$g_i=g_{i-1}+g_{i-2}+(2sum_{j=3}^{i-jge 0} [jmod 2=1]f_{i-j})+(2sum_{j=4}^{i-jge 0} [jmod 2=0]f_{i-j})$$
然后可以发现(sum_{j=3}^{i-jge 0} [jmod 2=1]f_{i-j}=f_{i-2}-1),(sum_{j=4}^{i-jge 0} [jmod 2=0]f_{i-j}=f_{i-3}),所以$$g_i=g_{i-1}+g_{i-2}+2(f_{i-2}-1)+2f_{i-3}$$
注意(n)很大,要使用矩乘优化
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db double
using namespace std;
const int mod=1e9+7;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
struct matrix
{
int a[6][6];
matrix(){memset(a,0,sizeof(a));}
void inii(){for(int i=0;i<6;++i) a[i][i]=1;}
matrix operator * (const matrix &bb) const
{
matrix an;
for(int i=0;i<6;++i)
for(int j=0;j<6;++j)
{
LL nw=0;
for(int k=0;k<6;++k) nw+=1ll*a[i][k]*bb.a[k][j];
an.a[i][j]=nw%mod;
}
return an;
}
matrix operator ^ (const LL &bb) const
{
matrix an,a=*this;
an.inii();
LL b=bb;
while(b)
{
if(b&1) an=an*a;
a=a*a,b>>=1;
}
return an;
}
}aa,bb;
int main()
{
aa.a[0][0]=aa.a[0][1]=1,aa.a[0][5]=mod-1;
bb.a[0][0]=bb.a[1][0]=bb.a[0][1]=bb.a[1][2]=1;
bb.a[3][3]=bb.a[4][3]=bb.a[3][4]=bb.a[5][5]=1;
bb.a[1][3]=bb.a[2][3]=2,bb.a[5][3]=2;
int T=rd();
while(T--) printf("%d
",(aa*(bb^(rd()-1))).a[0][3]);
return 0;
}