hdu 2089(数位DP)

来源:互联网 发布:子宫肌瘤微创手术知乎 编辑:程序博客网 时间:2024/05/17 03:10

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2089


解题思路:

数位dp.    dp[i][0]表示到第i位不含有不吉利数的个数(不包括第i位为2的),dp[i][1]表示到第i位不含有不吉利数且第i位为2的个数,dp[i][2]表示到第i位含有不吉利数的个数。

然后对题目给的m,n最大范围进行一次预处理,算出dp[i][0],dp[i][1],dp[i][2]各自的值。然后对于输入的n,m,各自算出到n,m总共有多少个不含不吉利数的个数,两者相减即为最终结果。


代码如下:

#include <iostream>#include <string.h>using namespace std;int dp[10][3];int a[10],b[10];int main(){    memset(dp,0,sizeof(dp));    dp[0][0]=1;    for(int i=1;i<=7;i++)    {        dp[i][0]=dp[i-1][0]*9 - dp[i-1][1];//当前不含不吉利的数由上一位不含不吉利的数乘以9(要去掉4那一位)减去开头含2的推出        dp[i][1]=dp[i-1][0];//开头含2的只要上一位不含不吉利数开头直接加2即可        dp[i][2]=dp[i-1][2]*10 + dp[i-1][1] + dp[i-1][0];        //之前含有不吉利数的,加上i位打头的任何数,还是不吉利数,然后加上开头含2的不含不吉利数的,因为i位只要为6,就会产生不吉利数        //然后再加上开头为4的                                                        }    int n,m,temp1,temp2;    while(cin>>n>>m)    {        if(n==0&&m==0)            break;        m++;        memset(a,0,sizeof(a));        memset(b,0,sizeof(b));        temp1=n;        temp2=m;        int len=1,last=0,flag=0;        long long ans1=0,ans2=0;        while(n!=0)        {            a[len]=n%10;            n/=10;            len++;        }        for(int i=len-1;i>=1;i--)        {            ans1 += dp[i-1][2]*a[i];//之前只要含有不吉利数,接下来开头无论是什么,都一定是不吉利数,所以直接乘            if(flag==1) ans1 += dp[i-1][0]*a[i];//如果前面较大的位数中已含有不吉利数,那么后面不管含没含,都一定是不吉利数            if(flag==0&&a[i]>4)                ans1 += dp[i-1][0];//开头为4的            if(flag==0&&last==6&&a[i]>2)                  ans1 += dp[i][1];//i+1位为6,i位为2的            if(flag==0&&a[i]>6)                ans1 += dp[i-1][1];//a[i]>6的话,开头就会有一次含有6,所以再加上以2打头的非不吉利数个数            if(a[i]==4||(last==6&&a[i]==2))//若前几位已经含有了不吉利数                  flag=1;            last=a[i];        }        ans1=temp1-ans1;        //m的计算类似,可以写个函数放在一起的OTZ        len=1,last=0,flag=0;        while(m!=0)        {            b[len]=m%10;            m/=10;            len++;        }        for(int i=len-1;i>=1;i--)        {            ans2 += dp[i-1][2]*b[i];            if(flag==1) ans2 += dp[i-1][0]*b[i];            if(flag==0&&b[i]>4)                ans2 += dp[i-1][0];            if(flag==0&&last==6&&b[i]>2)                 ans2 += dp[i][1];            if(flag==0&&b[i]>6)                ans2 += dp[i-1][1];            if(b[i]==4||(last==6&&b[i]==2))                 flag=1;            last = b[i];        }        ans2 = temp2-ans2;        cout<<ans2-ans1<<endl;    }    return 0;}



0 0
原创粉丝点击