HDU 6146:Pokémon GO

来源:互联网 发布:为什么程序员生女儿 编辑:程序博客网 时间:2024/06/05 17:59

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

3123

Sample Output

22496

题解

这是一个规律题首先,我们可以知道步数最少即为遍历每一个格子然后我们从顶点入手首先我们先画一个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(1<i<n)这一列的上面的格子为起点,我们会发现有两种选择① 向左边走,由于下面的点还需要遍历,所以有2^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<cstdio>#define tt 1000000007using 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);    }}
原创粉丝点击