[基础数位DP] HDU2089 不要62 HDU3555 Bomb

2个入门题。

HDU2089

题意: 求[L, R]范围内, 不含有数字4和62的数的个数。

记忆搜索的写法非常简单,已加入模板。

#include<bits/stdc++.h>
using namespace std;
int dp[15][2];
int num[15];
int dfs(int pos, int st, int f){ // st值 0表示不含4且不以6结尾 1表示不含4且以6结尾 2表示含有了4或者62,转移时其实直接舍去了,无需关注
    if(pos < 1) return 1; // 到0就返回啦 表示所有位都填上了一个数 并且是合法的
    if(!f && dp[pos][st] != -1) return dp[pos][st]; //如果已经搜过了就不用再搜了
    int end = f? num[pos] : 9;
    int ans = 0;
    for(int i = 0; i <= end; ++i){
        if(i == 4 || (st == 1 && i == 2)) continue; //当已出现4或者62的时候就不用搜了,搜了也肯定舍去
        else if(i == 6) ans += dfs(pos-1, 1, f && i == end);
        else ans += dfs(pos-1, 0, f && i == end);
    }
    if(!f) dp[pos][st] = ans; // 记忆化
    return ans;
}
int solve(int n){ //返回 [0, n]区间内不含4和62的个数
    int len = 0;
    while(n){
        num[++len] = n%10; // 位置0并没有定义
        n /= 10;
    }
    return dfs(len, 0, 1);
}
int main(){
    int n, m;
    memset(dp, -1, sizeof(dp)); //此题是不需要重复初始化的
    while(scanf("%d%d", &n, &m), n||m){
        printf("%d\n", solve(m)-solve(n-1)); //要注意n-1会不会为负
    }
}

HDU3555

题意:求[0, N]范围内,含49的数的个数,和上面类似。

#include<bits/stdc++.h>
#define ll long long int
using namespace std;
ll dp[25][3];
int num[25];
ll dfs(int pos, int st, int f){ // st值 0表示不含49且不以4结尾 1表示不含49且以4结尾 2表示含有49
    if(pos < 1) return st == 2; // 这题求含有49的,那就返回状态2
    if(!f && dp[pos][st] != -1) return dp[pos][st];
    int end = f? num[pos] : 9;
    ll ans = 0;
    for(int i = 0; i <= end; ++i){
        if(st == 2 || (st == 1 && i == 9)) ans += dfs(pos-1, 2, f && i == end);
        else if(i == 4) ans += dfs(pos-1, 1, f && i == end);
        else ans += dfs(pos-1, 0, f && i == end);
    }
    if(!f) dp[pos][st] = ans;
    return ans;
}
ll solve(ll n){
    int len = 0;
    while(n){
        num[++len] = n%10;
        n /= 10;
    }
    return dfs(len, 0, 1);
}
int main(){
    int T;
    memset(dp, -1, sizeof(dp));
    scanf("%d", &T);
    while(T--){
        ll n;
        scanf("%lld", &n);
        printf("%lld\n", solve(n));
    }
}

你可能感兴趣的:(dp,ACM,HDU)