您的位置:首页 > 其它

51nod_幸运号码

2018-02-03 15:44 134 查看
1043 幸运号码 


基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题


 收藏


 关注

1个长度为2N的数,如果左边N个数的和 = 右边N个数的和,那么就是一个幸运号码。
例如:99、1230、123312是幸运号码。

给出一个N,求长度为2N的幸运号码的数量。由于数量很大,输出数量 Mod 10^9 + 7的结果即可。

Input
输入N(1<= N <= 1000)


Output
输出幸运号码的数量 Mod 10^9 + 7


Input示例
1


Output示例
9


思路:

 打表出i位数时和为j的数量,用dp[i][j]表示;

 这里求的是2*n长度的数量,所以原本答案为(组合数)dp
[j]*dp
[j](j<=n*9) ,又因为前面一段的组合不能出现前导0,
比如 1001,这样可以。0101这就不满足4位数,所以要去掉前导0.
那问题就来了,该怎么去掉前导0。

举个例子:

当n=1时j等于2时组合有 2
当n=2时j等于2时 组合有 02 11 20 有前导0的数为 02
可以发现前n-1位数之和为n-1位时和为J的数量 

当n=3时j等于2时 组合有 011 020 002 101 110 200 有前导0的数为011 020 002 可以发现前n-1位数之和为n-1位时和为J的数量
当n=4时j等于2时 组合有 0011 0101 0110 0200 0020 0002 ...... 前导0的数为0011 0101 0110 0200 0020 0002
可以发现前n-1位数之和为n-1位时和为J的数量

那么去除前导0的数量就是 dp
[i] - dp[n-1][i] ;

#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
const int MOD = 1e9+7;
ll dp[1005][9099];
void init(){
dp[0][0] = 1;
for(int i=0;i<=9;i++){
dp[1][i] = 1;
}
for(int i=2;i<=1000;i++){
for(int j=0;j<=i*9;j++){
for(int k=0;k<=9&&k<=j;k++){
dp[i][j] = (dp[i][j]+dp[i-1][j-k])%MOD;
}
}
}
}
int main(){
init();
int n;
cin>>n;
/*if(n==1){
cout<<"9"<<endl;
goto END;
}*/
ll ans = 0;
for(int i=0;i<=9*n;i++){
ans = (ans+(ll)dp
[i]*(dp
[i]-dp[n-1][i]))%MOD;
}
cout<<ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: