HDU3555 Bomb(数位DP)

来源:互联网 发布:广州网络信息展会 编辑:程序博客网 时间:2024/06/11 18:49

数位DP入门级题目(我也只会做入门级题目0 0),求n以内的数字中不含有连续的49的数字有多少个。类似于另外一题http://acm.hdu.edu.cn/showproblem.php?pid=2089,照搬代码吧。另外一题题解,N久以前发的:传送门

先预处理,设dp[i][j]表示第i位数是j的方案数(j可以是0),不难得到dp[i][j] = sigma(dp[i-1][k])(0<=k<=9,k≠4且j≠9)。

模拟一下求和的原理,假设n = 23495,那么len = 5;第一遍循环求出来1xxxx和0xxxx的总方案数,也就是小于20000的总方案数;第二遍循环求出来20xxx和21xxx还有22xxx的总方案数;同理,第三遍求出来230xx,231xx,232xx,233xx;第四遍2340x,2341x,2342x,2343x,2344x,2345x,2346x,2347x,2348x,下一个是2349x,这个时候出现了49再求下去没有意义,于是循环终止。

#include<iostream>#include<cstring>using namespace std;typedef long long LL;LL dp[25][10];int digit[20];void init(){    dp[0][0] = 1;    for(int i = 1; i <= 20; i++)    {        for(int j = 0; j <= 9; j++)            for(int k = 0; k <= 9; k++)            {                if(k == 9&&j == 4) continue;                dp[i][j] += dp[i-1][k];            }    }}void dig(LL x,int &len){    memset(digit,0,sizeof digit);    while(x)    {        digit[++len] = x%10;        x /= 10;    }}LL cal(LL n){    LL ans = 0;    int len = 0;    dig(n,len);    for(int i = len; i >= 1; i--)    {            for(int j = 0; j < digit[i]; j++)        {                ans += dp[i][j];        }            if(digit[i] == 9&&digit[i+1] == 4) break;    }    return ans;}int main(){    init();    int T;    LL n;    cin>>T;    while(T--)    {        cin>>n;        cout<<n+1-cal(n+1)<<endl;    }}


0 0