HDU-2089不要62-暴力或数位DP入门

不要62

题意:给定区间,求在这个区间中有多少个数字,不包含4且不包含62;

这道题作为数位DP的入门题;

暴力也是可以过

#include<cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;

const int maxn =1e6+7;
int a[maxn];
bool check(int x)
{
    while(x>0)
    {
        if(x%10==4)return true;
        if(x%100==62)return true;
        x/=10;
    }
    return false;
}
int main(){
    int sum = 0;
    for(int i=1;i<=1000000;i++)
    {
        if(check(i)){a[i]=sum;continue;}
        sum++;
        a[i]=sum;
    }
    int l,r;
    while(~scanf("%d%d",&l,&r)&&l+r)
    {
        
        printf("%d
",a[r]-a[l-1]);
    }
    
    return 0;
}

当然数位DP更快,利用记忆化DFS

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdio>
using namespace std;

int dp[10][3],digit[10];
int dfs(int pos,bool pre_6,bool limit)
{
    if(pos==0)return 1;
    if(!limit&&dp[pos][pre_6]>=0)return dp[pos][pre_6];
    int ans=0,num=limit?digit[pos]:9;
    for(int i=0;i<=num;i++)
    {
        if(i==4||(pre_6&&i==2))
            continue;
        ans += dfs(pos-1,i==6,limit&&i==num); //只有之前有限制现在的达到了上限才能构成限制
    }
    return limit?ans:dp[pos][pre_6] = ans;//如果有限制,那么就不能记忆化,否则记忆的是个错误的数.

}
int solve(int x)
{
    int len = 0;
    while(x>0)
    {
        digit[++len]=x%10;  //将数字存在digit数组中
        x/=10;
    }
    return dfs(len,false,true);
}

int main(){
    memset(dp,-1,sizeof(dp));
    int l,r;
    while(scanf("%d%d",&l,&r),l+r)
    {
        printf("%d
",solve(r)-solve(l-1));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ckxkexing/p/8469833.html