poj 3252 Round Numbers

题目链接:http://poj.org/problem?id=3252

题意:如果一个数的二进制表示中它的0的个数大于或等于1的个数,那么这是一个Round Numbers。

给出一个区间,问这个区间中共有多少个Round Numbers。

思路:

记忆化搜索,判断最后的数的0和1的个数,但是要注意前导0的情况,要把前导0的个数去掉。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 int num[40];
 6 int dp[40][2][40][40];
 7 int dfs(int cur, int allzero, int one, int zero, int limit)
 8 {
 9     if(cur < 0)
10     {
11         if(!allzero && (zero >= one)) return 1;
12         else return 0;
13     }
14     if(!limit && dp[cur][allzero][one][zero] != -1) return dp[cur][allzero][one][zero];
15     
16     int ret = 0;
17     int up = limit?num[cur]:1;
18     for(int i = 0; i <= up; i++)
19     {
20         if(i == 0 && allzero == 0) ret += dfs(cur-1, allzero, one, zero+1, limit && i == up); 
21         else if(i == 0 && allzero == 1) ret += dfs(cur-1, allzero, 0, 0, limit && i == up);
22         else if(i == 1 && allzero == 0) ret += dfs(cur-1, allzero, one+1, zero, limit && i == up);
23         else if(i == 1 && allzero == 1) ret += dfs(cur-1, 0, one+1, zero, limit && i == up); 
24     }
25     if(!limit) dp[cur][allzero][one][zero] = ret;
26     return ret;
27 }
28 int slove(int x)
29 {
30     memset(dp, -1, sizeof(dp));
31     int cnt = 0;
32     while(x)
33     {
34         num[cnt++] = x%2;
35         x /= 2;
36     }
37     return dfs(cnt-1, 1, 0, 0, 1);
38     
39 }
40 int main() 
41 {
42    // freopen("in.txt", "r", stdin);
43    // freopen("out.txt", "w", stdout);
44     int n, m;
45     while(~scanf("%d%d", &n, &m))
46     {
47         printf("%d
", slove(m) - slove(n-1));
48     }
49     return 0;
50 }
原文地址:https://www.cnblogs.com/titicia/p/5233727.html