一、题目
二、解法
设
f
[
i
]
f[i]
f[i]为大小为
2
×
i
2\times i
2×i的矩阵填充的方案数,首先考虑不放特殊格子(
1
×
1
1\times 1
1×1),那么可以从
f
[
i
−
1
]
f[i-1]
f[i−1]和
f
[
i
−
2
]
f[i-2]
f[i−2]转移而来。考虑放特殊格子的情况,无论是放上面还是放下面,前面的格子的放法总是唯一的(和间隔的奇偶性有关),而且一定是要空两格的,设
g
[
i
]
g[i]
g[i]为大小为
2
×
i
2\times i
2×i的矩阵只用
2
×
1
2\times 1
2×1的小矩阵填充的方案数,那么
f
[
i
]
f[i]
f[i]还可以从
2
∑
j
=
1
i
−
3
g
[
j
]
2\sum_{j=1}^{i-3} g[j]
2∑j=1i−3g[j]转移过来,综上我们可以写出转移方程:
f
[
i
]
=
f
[
i
−
1
]
+
f
[
i
−
2
]
+
2
(
g
[
j
−
1
]
−
1
)
f[i]=f[i-1]+f[i-2]+2(g[j-1]-1)
f[i]=f[i−1]+f[i−2]+2(g[j−1]−1)这里对转移方程进行了简写,首先从
d
p
dp
dp的角度可得
g
g
g是一个斐波那契数列,要证明一个结论:
∑
i
=
1
n
g
[
i
]
=
g
[
n
+
2
]
−
1
\sum_{i=1}^n g[i]=g[n+2]-1
∑i=1ng[i]=g[n+2]−1,可以用归纳法,当
n
=
1
n=1
n=1时成立,假设
n
=
k
n=k
n=k时成立,那么
∑
i
=
1
k
g
[
i
]
+
g
[
k
+
1
]
=
g
[
k
+
2
]
−
1
+
g
[
k
+
1
]
\sum_{i=1}^k g[i]+g[k+1]=g[k+2]-1+g[k+1]
∑i=1kg[i]+g[k+1]=g[k+2]−1+g[k+1],即
∑
i
=
1
k
+
1
g
[
i
]
=
g
[
k
+
3
]
−
1
\sum_{i=1}^{k+1}g[i]=g[k+3]-1
∑i=1k+1g[i]=g[k+3]−1,故
n
=
k
+
1
n=k+1
n=k+1时也成立,证毕。
显然上面的
d
p
dp
dp可以用矩阵加速,如果不会构造矩阵的童鞋可以看下面的图:
时间复杂度
O
(
125
×
T
log
n
)
O(125\times T\log n)
O(125×Tlogn),贴个代码
q
w
q
qwq
qwq。
#include <cstdio>
#include <cstring>
#define int long long
const int MOD = 1e9+7;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int T,n;
struct Matrix
{
int n,m,a[8][8];
Matrix() {n=m=0;memset(a,0,sizeof a);}
Matrix operator * (const Matrix &b) const
{
Matrix r;
r.n=n;r.m=b.m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=b.m;k++)
{
r.a[i][k]=(r.a[i][k]+a[i][j]*b.a[j][k])%MOD;
r.a[i][k]=(r.a[i][k]+MOD)%MOD;
}
return r;
}
}A,F;
Matrix qkpow(Matrix a,int b)
{
Matrix r;
r.n=r.m=a.n;
for(int i=1;i<=r.n;i++)
r.a[i][i]=1;
while(b>0)
{
if(b&1) r=r*a;
a=a*a;
b>>=1;
}
return r;
}
signed main()
{
T=read();
while(T--)
{
n=read();
if(n<=2)
{
puts("0");
continue;
}
A.n=A.m=F.n=5;F.m=1;
A.a[1][1]=A.a[1][2]=A.a[2][1]=
A.a[3][3]=A.a[3][4]=A.a[4][3]=A.a[5][5]=1;
A.a[1][3]=2;A.a[1][5]=-2;
F.a[3][1]=2;F.a[4][1]=F.a[5][1]=1;
printf("%lld\n",(qkpow(A,n-2)*F).a[1][1]);
}
}