马要打电话

D.马要打电话

时间限制: C/C++ 3000ms; Java 6000ms 内存限制: 65535KB

通过次数: 10 总提交次数: 18

问题描述

国际象棋中马的走法如下

  image.png            

我们将马放在手机键盘上的任意数字键(如上图所示)上,接下来,马将会跳 N-1 步。每一步必须是从一个数字键跳到另一个数字键。

每当它落在一个键上(包初始位置),都会拨出键所对应的数字,总共按下 N 位数字。

你能用这种方式拨出多少个不同的号码?

因为答案可能很大,所以输出答案模 10^9 + 7

输入描述

多组样例输入,每次输入一个数字N(1<=N<=5000)

输出描述

输出拨出不同的号码个数

样例输入

1
2
3

样例输出

10
20
46

来源

admin

提示

emmmm,真的是菜的顶不住,orz ,比赛上考虑了很多,每个点能到达的点是哪个,到达之后那些点的方法数该如何记录,用dp还是搜索……真是被这幅图给吓到了,下来之后,又看了很长时间,思路还是那样,我现在……

话不多说,把每个点能到达的方法数记录下来,不断更新此时的步数可以到达点的方法数,dp存储方法数,a存储上一次的方法数,b是这一次的方法数

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll dp[5005];
ll b[13],a[13]={0,2,2,2,3,0,3,2,2,2,0,2,0};
int main() {
    ll n;
    dp[1]=10,dp[2]=20;
    for(ll i=3;i<5001;i++) {
        b[1]=a[6]+a[8];b[1]%=mod;
        b[2]=a[7]+a[9];b[2]%=mod;
        b[3]=a[4]+a[8];b[3]%=mod;
        b[4]=a[3]+a[9]+a[11];b[4]%=mod;
        b[6]=a[1]+a[7]+a[11];b[6]%=mod;
        b[7]=a[2]+a[6];b[7]%=mod;
        b[8]=a[1]+a[3];b[8]%=mod;
        b[9]=a[2]+a[4];b[9]%=mod;
        b[11]=a[4]+a[6];b[11]%=mod;
        for(ll j=1;j<=11;j++) {
            dp[i]=(dp[i]+b[j])%mod;
            a[j]=b[j];
        }
    }
    while(~scanf("%lld",&n)) {
        printf("%lld\n",dp[n]);
    }
}

 现在,我真的感觉,简单的……想哭………………………………………………

猜你喜欢

转载自blog.csdn.net/hou_shiyu/article/details/84928112