题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5491
题目大意:找出比D大的且二进制中1的个数位于区间[S1,S2]内的最小的数。
分析:对于给出的D,我们令D++,然后首先判断D是否属于区间[S1,S2],如果属于,那么D即为答案,否则无异于以下两种情况:
(1)D中1的个数小于S1,对于这种情况,我们需要做的就是在增加D的同时,增加其二进制中1的个数,我们从其二进制的低位(假设最低位的标号为0)开始找,找到第一个0(假设该位的标号为i),将该位的0变为1(即令D+2^i),然后继续判断;
(2)D中1的个数大于S2,对于这种情况,同理,我们需要从低位开始找,找到第一个1,将这个1变为0(同样是加上2^i),直至D满足题意为止。
需要注意的,给出的D是int类型的,但比D大的数可能会超过int,我们用long long来存。
实现代码如下:
#include <cstdio>
using namespace std;
typedef long long ll;
int main()
{
int t,T=1,s1,s2;
ll d;
scanf("%d",&t);
while(t--)
{
scanf("%I64d%d%d",&d,&s1,&s2);
d++;
while(true)
{
ll m=d;
int num=0,cnt=0,bri[35];
while(m)
{
if(m%2)
{
bri[num++]=1;
cnt++;
}
else bri[num++]=0;
m/=2;
}
if(cnt<s1)
{
int i=0;
for(;i<num;i++)
if(bri[i]==0) break;
d=d+(1<<i);
}
else if(cnt>s2)
{
int i=0;
for(;i<num;i++)
if(bri[i]==1) break;
d=d+(1<<i);
}
else break;
}
printf("Case #%d: %lld\n",T++,d);
}
return 0;
}