HDU 6146 Pokémon GO(dp+组合数学)

探讨了在一个2xn的棋盘上,从任意起点出发遍历所有格子的路径数量计算方法,利用递推公式求解,并通过模运算处理大数问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

一个2×n的棋盘,一个格子只能走向与其某维坐标差1的格子,问有多少条路径可以走遍所有格子

Input

第一行一整数T表示用例组数,每组用例输入一个整数n(1T100,1n10000)

Output

对于每组用例,输出方案数,结果模109+7

Sample Input

3
1
2
3

Sample Output

2
24
96

Solution

f(n)为从2×n的棋盘左上角出发,遍历所有格子后回到左下角的方案数,g(n)为从2×n的棋盘左上角出发,遍历所有格子的方案数,则f(1)=1,g(1)=1,g(2)=6(2×2的棋盘任意两点可达,故方案数即为除左上角的三个格子的排列数)

先求f(n),为使从左上角出发可以回到左下角,左上角第一步需要走到第二列的某个格子,然后遍历后n2列后回到第二列的另一个格子然后再回到左下角,故有f(n)=2f(n1)

再求g(n),考虑左下角的格子是第几个被经过的,如果是第二个被经过的,那么第一列被遍历,要走到第二列的某个格子然后遍历后n1列,方案数2g(n1),如果是第三个被经过的,那么第一步是从左上角走到第二列的某个格子,然后从这个格子走到左下角,再从左下角走到第二列剩下的一个格子里,再从这个格子走到第三列某个格子去遍历后n2个格子,方案数4g(n2),否则左下角只能是最后一个被经过的,方案数即为从左上角遍历所有格子回到左下角的方案数f(n),故有g(n)=f(n)+2g(n1)+4g(n2)

求出f(n),g(n)后,考虑求答案,如果起点在四个角的某一个,方案数为g(n),对答案贡献4g(n),如果起点在中间,枚举起点所在列i,第i列可以有两个起点,如果先往左走那么需要遍历前i列后回到第i列然后走到第i+1列后遍历后ni列,方案数4f(i)g(ni),如果先往右走那么需要遍历后ni+1列后回到第i列然后走到第i1列后遍历前i1列,方案数4f(ni+1)g(i1),故ans=4g(n)+4i=2n1(f(i)g(ni)+f(ni+1)g(i1))

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define maxn 10005 
#define mod 1000000007
ll f[maxn],g[maxn];
void init(int n=10000)
{
    f[1]=1;
    for(int i=2;i<=10000;i++)f[i]=f[i-1]*2%mod;
    g[1]=1;g[2]=6;
    for(int i=3;i<=10000;i++)g[i]=(f[i-1]*2+g[i-1]*2+g[i-2]*4)%mod;
}
int main()
{
    init();
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        if(n==1)printf("2\n");
        else
        {
            ll ans=g[n]*4%mod;
            for(int i=2;i<n;i++)
                ans=(ans+(f[i]*g[n-i]+f[n-i+1]*g[i-1])*4%mod)%mod;
            printf("%I64d\n",ans);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值