快捷搜索: 王者荣耀 脱发

HDU6148 Valley Numer {DP}【数位DP】

题解

    查找区间 [ 0 , n ] [0, n] [0,n]内有多少个数字上没有峰值的数字。注意 12221 12221 12221也算有峰值。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define lowbit(x) ((x) & -(x));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 1e5 + 10, NN = 1e3 + 10, INF = 0x3f3f3f3f, LEN = 110;
const ll MOD = 1e9 + 7;
const ull seed = 31;
ll digit[LEN];
ll dp[LEN][10][3];  //三维下标为0表示不确定前面的状态,1表示递减,2表示递增
ll dfs(ll len, bool ismax, ll isup, ll last, bool lead_zero) {
          
   
    // lead_zero表示是否处理到了可以处理的数字,意思就是是否已经抛弃了前导零
    ll ans = 0;
    if (!len)
        return lead_zero ? 1LL : 0LL;
    //若已经抛弃前导零找到可以处理的数字则输出1
    if (!ismax && dp[len][last][isup] != -1)
        return dp[len][last][isup];
    ll maxx = ismax ? digit[len] : 9LL;
    for (ll i = 0; i <= maxx; i++) {
          
   
        if (isup == 2 && i < last)
            continue;
        //若isup已经为2就是之前已经出现递增,若i<last则在递增后又出现了递减,不允许出现这种情况,跳过
        else if (!lead_zero && i == 0)
            ans =
                (ans + dfs(len - 1, ismax && i == maxx, isup, i, false)) % MOD;
        //若还在前导零的范围内并且i还是0,则lead_zero继续为false
        else if (!lead_zero)
            ans = (ans + dfs(len - 1, ismax && i == maxx, isup, i, true)) % MOD;
        //若找到了可以处理的数字并且这个数字之前是前导零
        else if (i == last)
            ans = (ans + dfs(len - 1, ismax && i == maxx, isup, i, true)) % MOD;
        //若i与前一个相同
        else
            ans = (ans + dfs(len - 1, ismax && i == maxx, i > last ? 2 : 1, i,
                             true)) %
                  MOD;
        //若不同
    }
    if (!ismax)
        dp[len][last][isup] = ans;
    return ans;
}
ll solve(char str[]) {
          
   
    ll len = 0;
    for (ll i = strlen(str) - 1; i >= 0; i--)
        digit[++len] = str[i] - 0;
    return dfs(len, true, 0, -1, false);
}
void init() {
          
   
    memset(dp, -1, sizeof dp);
}
int main() {
          
   
    int t;
    scanf("%d", &t);
    init();
    while (t--) {
          
   
        char n[NN];
        scanf("%s", n);
        printf("%lld
", solve(n));
    }
    return 0;
}
经验分享 程序员 微信小程序 职场和发展