您的位置:首页 > 其它

poj 3252 Round Numbers

2016-03-02 09:45 239 查看
题目链接:http://poj.org/problem?id=3252

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

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

思路:

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

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int num[40];
int dp[40][2][40][40];
int dfs(int cur, int allzero, int one, int zero, int limit)
{
if(cur < 0)
{
if(!allzero && (zero >= one)) return 1;
else return 0;
}
if(!limit && dp[cur][allzero][one][zero] != -1) return dp[cur][allzero][one][zero];

int ret = 0;
int up = limit?num[cur]:1;
for(int i = 0; i <= up; i++)
{
if(i == 0 && allzero == 0) ret += dfs(cur-1, allzero, one, zero+1, limit && i == up);
else if(i == 0 && allzero == 1) ret += dfs(cur-1, allzero, 0, 0, limit && i == up);
else if(i == 1 && allzero == 0) ret += dfs(cur-1, allzero, one+1, zero, limit && i == up);
else if(i == 1 && allzero == 1) ret += dfs(cur-1, 0, one+1, zero, limit && i == up);
}
if(!limit) dp[cur][allzero][one][zero] = ret;
return ret;
}
int slove(int x)
{
memset(dp, -1, sizeof(dp));
int cnt = 0;
while(x)
{
num[cnt++] = x%2;
x /= 2;
}
return dfs(cnt-1, 1, 0, 0, 1);

}
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int n, m;
while(~scanf("%d%d", &n, &m))
{
printf("%d\n", slove(m) - slove(n-1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: