hdu4734(数位dp)
给定 a和b,
问区间[0,b]内有多少个数字的f(i) <=f(a)
dp[i][s] 表示i位的数字的f<=s
所以比如如果第i+1位选择数字5之后, 那么只要剩下的i位数字的f<=f(a) - 5*2^i 即可。
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <algorithm> 5 #include <iostream> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <string> 12 #include <math.h> 13 using namespace std; 14 #pragma warning(disable:4996) 15 #pragma comment(linker, "/STACK:1024000000,1024000000") 16 typedef long long LL; 17 const int INF = 1<<30; 18 /* 19 4599 20 满足一个性质, 但是这个性质是会变化的 21 */ 22 int num[12]; 23 int bit[12]; 24 int dp[12][5555]; 25 void init() 26 { 27 bit[0] = 1; 28 for (int i = 1; i <= 10; ++i) 29 bit[i] = bit[i - 1] * 2; 30 } 31 32 33 34 int dfs2(int pos, int sta, bool flag) 35 { 36 if (sta < 0) return 0; 37 if (pos == 0) return 1; 38 if (!flag && dp[pos][sta] != -1) 39 return dp[pos][sta]; 40 int end = flag ? num[pos] : 9; 41 int ans = 0; 42 for (int i = 0; i <= end; ++i) 43 { 44 ans += dfs2(pos - 1, sta - bit[pos - 1] * i, flag&&i == end); 45 } 46 if (!flag) 47 dp[pos][sta] = ans; 48 return ans; 49 } 50 int calc(int sta, int n) 51 { 52 int len = 0; 53 while (n) 54 { 55 num[++len] = n % 10; 56 n /= 10; 57 } 58 return dfs2(len, sta, true); 59 } 60 int main() 61 { 62 init(); 63 memset(dp, -1, sizeof(dp)); 64 int t,a,b; 65 scanf("%d", &t); 66 for (int k = 1; k <= t; ++k) 67 { 68 scanf("%d%d", &a, &b); 69 int len = 0, sta = 0; 70 while (a) 71 { 72 num[++len] = a % 10; 73 a /= 10; 74 } 75 for (int i = len; i >= 1; --i) 76 sta += bit[i - 1] * num[i]; 77 printf("Case #%d: %d\n",k, calc(sta,b)); 78 } 79 return 0; 80 }