HDU 6148 Valley Numer(数位DP)

题意:问小于n的数有多少个V型的数字

思路:定义dp[i][j][k]表示第i位,前一个数为j,k==0表示非上升,k==1表示上升,转移一下就好了

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MOD = 1e9 + 7;

LL dp[105][15][5];
char b[105];
int a[105];
LL dfs(int pos, int pre, int state, int limit)
{
//    printf("st pos == %d pre == %d state == %d limit == %d\n", pos, pre, state, limit);
    if (pos == -1) {
        return 1;
    }
    if (!limit && dp[pos][pre][state] != -1) return dp[pos][pre][state];
    int up = limit ? a[pos] : 9;
    LL res = 0;
    if (state) {
        for (int i = pre; i <= up; i++) {
            res += dfs(pos - 1, i, 1, limit && i == up);
            if(res >= MOD) res %= MOD;
        }
    }
    else {
        for (int i = 0; i <= up; i++) {
            if(i <= pre) {
                if(!i && pre == 10)
                    res += dfs(pos - 1, 10, 0,limit && i == up);
                else
                    res += dfs(pos - 1, i, 0, limit && i == up);
            }
            else{
                res += dfs(pos - 1, i, 1, limit && i == up);
            }
            if(res >= MOD) res %= MOD;
        }
    }
    if(!limit) dp[pos][pre][state] = res;
//    printf("test pos == %d pre == %d state == %d limit == %d res == %lld\n", pos, pre, state, limit, res);
    return res;
}
LL solve()
{
    int pos = strlen(b);
    for (int i = 0, j = pos - 1; i < pos; i++, j--) {
        a[i] = b[j] - '0';
    }
    return dfs(pos - 1, 10, 0, true);
}
int main()
{
    memset(dp, -1, sizeof(dp));
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%s", b);
        printf("%lld\n", (solve() - 1 + MOD) % MOD );
    }
    return 0;
}
/*
3
3
14
120
*/

猜你喜欢

转载自www.cnblogs.com/lalalatianlalu/p/10716581.html