HDU 6146:Pokémon GO

HDU 6146:Pokémon GO


题目

Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description
众所周知,度度熊最近沉迷于 Pokémon GO。

今天它决定要抓住所有的精灵球!

为了不让度度熊失望,精灵球已经被事先放置在一个2*N的格子上,每一个格子上都有一个精灵球。度度熊可以选择任意一个格子开始游戏,抓捕格子上的精灵球,然后移动到一个相邻的至少有一个公共点的格子上继续抓捕。例如,(2, 2) 的相邻格子有(1, 1), (2, 1) 和 (1, 2) 等等。

现在度度熊希望知道将所有精灵球都抓到并且步数最少的方案数目。两个方案被认为是不同,当且仅当两个方案至少有一步所在的格子是不同的。

Input
第一行为T,表示输入数据组数。

每组数据包含一个数N。

●1≤T≤100

●1≤N≤10000

Output
对每组数据输出方案数目,结果对 1 000 000 007 取模。

Sample Input

3
1
2
3

Sample Output

2
24
96

题解

这是一个规律题

首先,我们可以知道步数最少即为遍历每一个格子

然后我们从顶点入手

首先我们先画一个2*N的格子图,我们设2*N的方格四个角上的格子所能走的方案数为f[n],然后以左上角的格子为起点(因为四个角上所走的方案数是相等的)我们会发现我们开始有三个选择:

① 先向下走,然后我们会发现我们可以走到一个2*N-1的方格的两个角上中的一个,即有2*f[n-1]种走法;

② 先向右走,然后我们有两个选择:

    ① 向左下的格子走,然后只能想右走,然后我们发现我们可以走到一个2*N-2的方格的两个角上中的一个,即有2*f[n-2]种走法;

    ② 向右边的两个格子走,因为还有下面和右下的格子没走,所以走法之有2^n-2种;

③ 先向右下走,然后我们又有两个选择:

    ① 向左的格子走,然后只能想右上走,然后我们发现我们可以走到一个2*N-2的方格的两个角上中的一个,即有2*f[n-2]种走法;

    ② 向右边的两个格子走,因为还有左边和上面的格子没走,所以走法之有2^n-2种;

所以顶点的方案数的规律就是f[n]=2*f[n-1]+4*f[n-2]+2^n-1

接下来我们找边界上的点的规律

我们假设以i(12^i-1种方案会到达下面的点,然后我们又会发现右边有一个2*n-i的方格的两个角上中的一个,即有2*f[n-i]种走法;

② 向右边走,由于下面的点还需要遍历,所以有2^n-i种方案会到达下面的点,然后我们又会发现左边有一个2*i-1的方格的两个角上中的一个,即有2*f[i-1]种走法;

所以边界的点的方案数的规律就是2*(f[n-i]*2^i-1+f[i-1]*2^n-1)

由此,我们只需要将没个点的方案数加在一起就是答案

(写了好长。。。手有点小累。。。)

代码

#include
#define tt 1000000007
using namespace std;

int t,n;
long long ans,f[10005],g[10005];

int main()
{
    scanf("%d",&t);
    f[1]=1;f[2]=6;g[1]=2;g[2]=4;
    for (int i=3;i<=10005;i++)
    {
        g[i]=(g[i-1]*2)%tt;
        f[i]=((f[i-1]*2)%tt+g[i-1]%tt+4*f[i-2])%tt;
    }
    while (t--)
    {
        scanf("%d",&n);
        if (n==1) ans=2;
         else ans=4*f[n];
        for (int i=2;i<=n-1;i++)
         ans=(ans+(4*((g[n-i]*f[i-1])%tt+(g[i-1]*f[n-i])%tt)%tt)%tt)%tt;
        printf("%lld\n",ans);
    }
}

你可能感兴趣的:(数学,HDU)