loj 1032 数位dp

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

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

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 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

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值