hdu4734(数位dp)

hdu4734

给定 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
",k, calc(sta,b));
78     }
79     return 0;
80 }
View Code
原文地址:https://www.cnblogs.com/justPassBy/p/4715493.html