我们设 Bn 代表从某个角出发,然后走遍所有格子回到同一列的方案数目。
Bn=2×Bn−1=2n−1
同样,我们设 An 代表从某个角出发,然后走遍所有格子的方案数。
则 An=Bn+2×An−1+4×An−2
其中 Bn 代表回到了当前列的方案数, An−1 代表先填满当前列然后走到相邻的列处理同样的一个子问题,
An−2 代表通过对角线方式先走完当前列与相邻列的格子,然后剩下的 n−2 列即相同子问题。
因为有四个角,所以我们的结果要乘以 4 ,即 4×An 。
当然,真实情况下我们不一定是从四个角出发的,还有另一种情况就是中间的列
考虑中间的第 i 列
我们可以先从第 i 列往左走完所有的格子回来,然后再往右走完所有的格子;
也可以先往右走完所有的格子回来,再往左走完所有的格子。
于是总的方案数即 2×(4×Bi−1×An−i+4×Bn−i×Ai−1) ,其中 2 代表第 i 列有两个格子可选为初始点, 4 代表分别向左右两边行走时的选择方案数 2×2 。
#include<cstdio> #define ll long long const int N=10010,P=1000000007; ll a[N],b[N],n; int T; int main() { register int i,j; b[1]=1; for (i=2;i<=N;i++) b[i]=(b[i-1]*2)%P; a[1]=1;a[2]=6; for (i=3;i<=N;i++) a[i]=(2*a[i-1]+b[i]+4*a[i-2])%P; scanf("%d",&T); for (j=1;j<=T;j++) { int n;scanf("%d",&n);ll ans=0; for (i=2;i<=n-1;i++) ans=(ans+16*b[i-1]%P*a[n-i])%P; ans=(ans+4*a[n])%P; if (n==1) ans=2; printf("%lld\n",ans); } return 0; }