HDU 6146 && 2017 百度之星复赛 1003 Pokémon GO(递推)

来源:互联网 发布:vb多线程实例 编辑:程序博客网 时间:2024/05/20 13:04

题意:给你一个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;}