数位DP || Gym 101653RRamp Number
Posted 舒羽倾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数位DP || Gym 101653RRamp 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; }
以上是关于数位DP || Gym 101653RRamp Number的主要内容,如果未能解决你的问题,请参考以下文章
每日dp Gym - 101889E Enigma 数位dp 记忆化搜索