很明显的,有“大于”和“小于等于”两种情况,且一旦“大于”了,只能继续“大于”下去,如果“小于等于”,还可以选择任意一种情况。于是乎,直接数位dp,并且记录这一位是“大于状态”还是“小于等于状态”,就可以进行记忆化了。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <string> 5 #include <cstring> 6 #include <algorithm> 7 #include <limits> 8 #include <vector> 9 #include <stack> 10 #include <queue> 11 #include <set> 12 #include <map> 13 #include <bitset> 14 #include <unordered_map> 15 #include <unordered_set> 16 #define lowbit(x) ( x&(-x) ) 17 #define pi 3.141592653589793 18 #define e 2.718281828459045 19 #define INF 0x3f3f3f3f 20 #define HalF (l + r)>>1 21 #define lsn rt<<1 22 #define rsn rt<<1|1 23 #define Lson lsn, l, mid 24 #define Rson rsn, mid+1, r 25 #define QL Lson, ql, qr 26 #define QR Rson, ql, qr 27 #define myself rt, l, r 28 #define pii pair<int, int> 29 #define MP(a, b) make_pair(a, b) 30 using namespace std; 31 typedef unsigned long long ull; 32 typedef unsigned int uit; 33 typedef long long ll; 34 const int maxN = 1e2 + 7; 35 const ll mod = 1e9 + 7; 36 void MOD(ll & x) { x >= mod ? x %= mod : x; } 37 char s[maxN]; 38 int N, dig[maxN]; 39 ll dp[maxN][10][2]; 40 ll dfs(int pos, int x, bool op, bool top, bool zero) 41 { 42 if(pos == 1) return !zero; 43 if(!top && (~dp[pos][x][op])) return dp[pos][x][op]; 44 ll sum = 0; 45 int u = top ? dig[pos - 1] : 9; 46 for(int i = 0; i <= u; i ++) 47 { 48 if(op) 49 { 50 if(i < x) continue; 51 sum += dfs(pos - 1, i, true, top && i == u, zero && (!i)); 52 MOD(sum); 53 } 54 else 55 { 56 sum += dfs(pos - 1, i, !zero && i > x, top && i == u, zero && (!i)); 57 MOD(sum); 58 } 59 } 60 if(!top && !zero) dp[pos][x][op] = sum; 61 return sum; 62 } 63 int main() 64 { 65 int T; scanf("%d", &T); 66 while(T --) 67 { 68 scanf("%s", s); 69 N = (int)strlen(s); 70 for(int i = 0; i < N; i ++) dig[N - i] = s[i] - '0'; 71 memset(dp, -1, sizeof(dp)); 72 printf("%lld\n", dfs(N + 1, 0, false, true, true)); 73 } 74 return 0; 75 }