数位DP || Gym 101653R Ramp Number

每一位都大于等于前一位的数叫Ramp Number

给一个数,如果不是Ramp Number输出-1,如果是Ramp Number输出比它小的Ramp Number的个数

只和每一位上的数字有关

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
char s[88];
long long f[88][11];//数位dp
int main()
{
    int T;
    scanf("%d", &T);
    memset(f, 0, sizeof(f));
    for(int i = 0; i <= 9; i++) f[1][i] = 1;
    for(int i = 2; i <= 80; i++)
    {
        for(int j = 0; j <= 9; j++)
        {
            for(int k = j; k <= 9; k++)
                f[i][j] += f[i - 1][k];
        }
    }
    /*f[i][j]表示长度为i以j开头的这样的数有多少个
     *f[i][j] = sum(f[i-1][k]) k>=j
     *例如f[3][5] 表示长度为3,以5开头的上升数的个数 即333,334,335,336……
     *只看后两位 33,34,35…… 44,45,46……
     *是长度为2,以3开头的+长度为2,以4开头的+……
     */
     /*
      *加的时候如1345 -> f[4][0] + f[3][1] + f[3][2] + f[2][3] + f[2][4] + f[1][4] + f[1][5]
      *f[4][0] 所有一二三位数,然后固定第一位是1
      *f[3][x] (x >= 1 && x < 3) 取的这些三位数后在前面放1就是结果,然后固定第二位是3
      *以此类推
      */
    while(T--)
    {
        scanf("%s", s);
        int len = strlen(s);
        int flag = 1;
        for(int i = 1; i < len; i++)
        {
            if(s[i] < s[i - 1])
                flag = 0;
        }
        if(!flag)
        {
            printf("-1\n");
            continue;
        }
        long long ans = 0;
        for(int i = 1; i <= len; i++)
        {
            for(int j = i == 1?0:s[i-2] - '0'; j < s[i-1] - '0'; j++)
            {
                ans += f[len-i+1][j];
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/pinkglightning/p/8978034.html