您的位置:首页 > 其它

POJ3252 Round Numbers【组合问题】

2015-08-31 21:34 477 查看
题目链接:
http://poj.org/problem?id=3252

题目大意:
给你两个十进制数 A 和 B,求其对应闭区间 [A,B] 内有多少个Round Numbers。
Round Numbers 是指:如果一个十进制数对应的二进制数中的 0 的个数多于 1 的
个数,则该数就是一个 Round Numbers。

解题思路:
参考博文:http://www.cnblogs.com/lyy289065406/archive/2011/07/31/2122758.html
计算闭区间 [A,B] 内有多少个Round Numbers,只需要分别求出[0,A] 内有多少
个Round Numbers,[0,B+1] 内有多少个Round Numbers,然后后者减去前者即
可。
那么如何来求[0,A]闭区间的 Round Numbers。
第一步先把 A 转换为二进制数,存入数组 Binary[] 数组中,其中 Binary[0]存放二进
制数数位长度。
再分为两部分计算区间内 Round Numbers:

①长度小于二进制数位长度 Binary[0] 的部分:

这部分的最高位肯定为 1,剩下数位可供放入数字的位数为 Binary[0]-1,从低位向高

位考虑情况。方案数和sum要加上各种放置情况。

for(int i = 1; i < Binary[0]-1; ++i)
{
for(int j = i/2+1; j <= i; ++j)
sum += C[i][j];
}

②长度等于二进制数位长度 Binary[0]的部分:

从高位向低位搜索除最高位外置为 1 的数位,并统计 1 的位数,然后方案数 sum

加上各种情况。

int Zero = 0;
for(int i = Binary[0]-1; i >= 1; --i)
{
if(Binary[i])
{
for(int j = (Binary[0]+1)/2-(Zero+1); j <= i-1; ++j)
sum += C[i-1][j];
}
else
Zero++;
}


AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

int C[33][33];

void ZuHe()
{
C[0][0] = C[1][0] = C[1][1] = 1;
for(int i = 2; i <= 32; ++i)
{
C[i][0] = C[i][i] = 1;
for(int j = 1; j < i; ++j)
C[i][j] = C[i-1][j] + C[i-1][j-1];
}
}

int Binary[35];

void Change(int N)
{
Binary[0] = 0;
while(N)
{
++Binary[0];
Binary[Binary[0]] = N%2;
N /= 2;
}
}

int Solve(int N)
{
Change(N);
int sum = 0;

for(int i = 1; i < Binary[0]-1; ++i)
{
for(int j = i/2+1; j <= i; ++j)
sum += C[i][j];
}

int Zero = 0;
for(int i = Binary[0]-1; i >= 1; --i)
{
if(Binary[i])
{
for(int j = (Binary[0]+1)/2-(Zero+1); j <= i-1; ++j)
sum += C[i-1][j];
}
else
Zero++;
}
return sum;
}
int main()
{
ZuHe();
int A,B;
while(~scanf("%d %d",&A,&B))
{
printf("%d\n", Solve(B+1)-Solve(A));
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: