loj 1032 数位dp

题目链接:http://lightoj.com/volume_showproblem.php?problem=1032

思路:数位dp, 采用记忆化搜索, dp[pos][pre][have] 表示 pos处,前一位为pre, 当前有have个满足条件的状态。

 1 #include 
 2 #include 
 3 #include 
 4 #include 
 5 using namespace std;
 6 
 7 long long dp[34][2][34];
 8 int n, digit[34];
 9 
10 long long dfs(int pos, int pre, int have, int doing)
11 {
12     if (pos == -1) {
13         return have;
14     }
15     if (!doing && dp[pos][pre][have] != -1) {
16         return dp[pos][pre][have];
17     }
18     int end = doing ? digit[pos] : 1;
19     long long ans = 0;
20     for (int i = 0; i <= end; i++) {
21         int nhave = have;
22         if (pre == 1 && i == 1) {
23             nhave++;
24         }
25         ans += dfs(pos - 1, i, nhave, i == end && doing);
26     }
27     if (!doing) {
28         dp[pos][pre][have] = ans;
29     }
30     return ans;
31 }    
32 
33 long long Solve(int n)
34 {
35     int pos = 0;
36     while (n) {
37         digit[pos] = n % 2;
38         n /= 2;
39         pos++;
40     }
41     return dfs(pos - 1, 0, 0, 1);
42 }
43 
44 int main()
45 {
46     memset(dp, -1, sizeof(dp));
47     int _case, t = 1;
48     scanf("%d", &_case);
49     while (_case--) {
50         scanf("%d", &n);
51         printf("Case %d: %lld\n", t++, Solve(n));
52     }
53     return 0;
54 }
55 
56 
57         
View Code

 

 

你可能感兴趣的:(loj 1032 数位dp)