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

HDU 2089 不要62(数位DP)

时间:2017-08-13 22:14:05      阅读:192      评论:0      收藏:0      [点我收藏+]

标签:--   strong   str   cst   记忆化   应用   bre   pac   init   

题意:求[n,m]内所有数字中不出现4也不出现连续62的数的个数。

输入:n m,多组数据,以0 0结尾。

输出:符合条件的数的个数。

限制:(0<n≤m<1000000) 时间:1000 ms 空间:32768 kB

分析:我们引入数位DP的应用范围:求出在给定区间[A,B]内,符合条件P(i)的数i的个数.条件P(i)一般与数的大小无关,而与 数的组成 有关.

           本题我们采用打表+递推的DP思路解题,空间复杂度比记忆化搜索略高,但便于理解。

#include <cstring>
#include <cstdio>
int dp[10][10];//dp[i][j]表示第i位为j时符合条件的数的个数 
void init(){//打表 
    memset(dp,0,sizeof(dp));
    dp[0][0]=1;
    for(int i=1;i<=7;i++)
    for(int j=0;j<10;j++)//枚举第i位可能出现的数
    for(int k=0;k<10;k++)//枚举第i-1位可能出现的数
    if(j!=4&&!(j==6&&k==2)) dp[i][j]+=dp[i-1][k];
}
int solve(int n){
    //printf("%d********%d*********%d\n",dp[4][2],dp[5][6],dp[5][7]); 
    int digit[10],len=0,ans=0;
    while(n>0){
        digit[++len]=n%10;
        n/=10;
    }
    digit[len+1]=0;
    for(int i=len;i;i--){//从高位到低位,每一位ans都加上所有符合条件的值,不重不漏 
        for(int j=0;j<digit[i];j++) if(j!=4&&!(digit[i+1]==6&&j==2)) ans+=dp[i][j];
        if(digit[i]==4||(digit[i]==2&&digit[i+1]==6)) break;//继续循环不可能再有符合题意的值,故直接跳出 
    }
    return ans;
}
int main(){
    int l,r;
    init();
    while(scanf("%d%d",&l,&r),l){
        printf("%d\n",solve(r+1)-solve(l));//区间相减,注意左闭右开 
    }
    return 0;
}

 

HDU 2089 不要62(数位DP)

标签:--   strong   str   cst   记忆化   应用   bre   pac   init   

原文地址:http://www.cnblogs.com/fushang/p/7354920.html

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