题意:给你一个2*n的网格,你可以从任意一点出发,每次可以向附近走一步,包括斜对角,走完所有格子且所有格
子恰好走一遍的方案数。
思路:nyoj980原题,思路见:点击打开链接
摘自他的:
一共有两个递推数组:
首先设Dn表示从左边或者右边的某个角出发,然后走遍所有格子回到同一列有多少种方法。
明显D1=2,Dn=2*Dn-1
所以Dn=2^n
然后设An表示从某个角出发,走遍所有格子(不一定回到同一列)有多少种方法。
An=Dn+2*An-1+4*An-2
这个递推公式就用统计原理分析出来,分别对应三种不同的走法
Dn对应从这个角走到下一列,然后走遍所有格子回到下一列,再回到这列的走法
2*An-1表示直接走到这列的另一个角,然后再走其他的地方
4*An-2表示走对角线方法走遍前两列,然后走其他的地方
这样答案如果从四个角出发,总数就是4*An
然后分析从某一列开始,假设第i列(1<i<n)
则总数为2*(2*Di-1*An-i+2*Dn-i*Ai-1)
对i从2到n-1全部加和,得到这部分答案
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e5+5;
const int mod = 1e9+7;
typedef long long ll;
ll a[maxn] = {1, 1, 6}, fac[maxn] = {1, 1};
void init()
{
for(int i = 2; i < maxn; i++)
fac[i] = fac[i-1]*2%mod;
}
int main(void)
{
init();
int _, n;
cin >> _;
while(_--)
{
scanf("%d", &n);
if(n == 1) { puts("2"); continue; }
for(int i = 3; i <= n; i++)
a[i] = (((a[i-1]*2)%mod+fac[i])%mod+(a[i-2]*4)%mod)%mod;
ll ans = a[n]*4%mod;
for(int i = 2; i <= n-1; i++)
ans = (ans+(((fac[n-i]*8)%mod*a[i-1]%mod)%mod+((a[n-i]*8)%mod*fac[i-1]%mod)%mod)%mod)%mod;
printf("%I64d\n", ans);
}
return 0;
}