D.马要打电话
时间限制: C/C++ 3000ms; Java 6000ms 内存限制: 65535KB
通过次数: 10 总提交次数: 18
问题描述
国际象棋中马的走法如下
我们将马放在手机键盘上的任意数字键(如上图所示)上,接下来,马将会跳 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]);
}
}
现在,我真的感觉,简单的……想哭………………………………………………