码迷,mamicode.com
首页 > 其他好文 > 详细

【Hdu2089】不要62(数位DP)

时间:2017-12-22 21:55:03      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:ems   logs   rip   代码   void   开头   +=   math   for   

Description

题目大意:给定区间[n,m],求在n到m中没有“62“或“4“的数的个数。

如62315包含62,88914包含4,这两个数都是不合法的。

0<n<=m<1000000

Solution

数位DP,首先预处理数组\(F[i][j]\),表示位数为\(i\),开头为\(j\)时,满足条件的数的个数

对于区间\([l,r]\)转化为求\([0,r]-[0,l)\)即可

对于区间\([0,n]\)将n按位数存储分别计算,

这样最后算出来的个数实际上为\([0,r)\)的,所以计算时上界应该+1

计算个数时如遇到4或62直接退出,详见代码

Code

#include <cstdio>
#include <cstring>

int n,m,f[10][10];

inline void Init(){
    memset(f,0,sizeof(f));
    f[0][0]=1;
    for(int i=1;i<=7;++i)
        for(int j=0;j<=9;++j)
            for(int k=0;k<=9;++k)
                if(j!=4&&!(k==2&&j==6))//注意6和2的位置
                    f[i][j]+=f[i-1][k];
}

int DP(int k){
    if(!k) return 0;
    int len=0,d[10],r=0;
    while(k){
        d[++len]=k%10;
        k/=10;
    }
    d[len+1]=0;
    for(int i=len;i;i--){
        for(int j=0;j<d[i];++j)
            if(j!=4&&!(j==2&&d[i+1]==6))
                r+=f[i][j];
        if(d[i]==4||(d[i]==2&&d[i+1]==6))//直接跳出
            break;
    }
    return r;
}

int main(){
    while(~scanf("%d%d",&n,&m)&&n+m){
        Init();
        printf("%d\n",DP(m+1)-DP(n));
    }
    return 0;
} 

【Hdu2089】不要62(数位DP)

标签:ems   logs   rip   代码   void   开头   +=   math   for   

原文地址:http://www.cnblogs.com/void-f/p/8087467.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!