51nod 1043 幸运数字(数位dp)

来源:互联网 发布:多益网络待遇 编辑:程序博客网 时间:2024/05/22 10:40

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

用f[i][j]表示i个数的和为j的总数,这里面是包括0开头的情形,有f[i][j]=f[i-1]j-k。很好想,i个数组成总和为j的数量就来自于i-1个数 里面能 在最前面加0到9的数字使得加完之后和为j。
这里面包含了0开头的,把0去掉的方法就是f[i][j]-f[i-1][j]。f[i-1][j]就代表了在i个数中,开头为0的个数,减去就是i个数中开头不为0的个数。原因很明显,i个数和为j与i-1个数和为j,就差了一个位置为0。而这一个位置因为一开始咱们的想法就是在最前面加的数字,所以这个位置就差在了最前面的位置上。

然后这里因为递推只用到了前一项的结果,用i&1(相当于mod2)的方式存储两位就好了,节省下内存。

#include<cstring>#include<string>#include<cstdio>#include<cstdlib>#include<iostream>#include<cmath>#include<algorithm>#include<queue>#include<vector>#include<map>#include<stack>#include<climits>#include<cctype>#include<bitset>#include<set>using namespace std;#define mod 1000000007#define PI acos(-1.0)#define INF 0x3f3f3f3ftypedef long long LL;const int MAX=1005;LL f[2][MAX*9];int main(){    int n;    memset(f,0,sizeof(f));    cin>>n;    f[0][1]=1;//为了1特判    for(int i=0;i<10;i++)        f[1][i]=1;    for(int i=2;i<=n;i++){        for(int j=0;j<=i*9;j++){            LL sum=0;            for(int k=0;k<10;k++){                if(j>=k)                    sum=(sum+f[(i-1)&1][j-k])%mod;            }            f[i&1][j]=sum;        }    }    LL ans=0;    for(int i=0;i<=n*9;i++){        ans=(ans+f[n&1][i]*(f[n&1][i]-f[(n-1)&1][i]))%mod;    }    cout<<ans<<endl;    return 0;}
0 0
原创粉丝点击