题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5491
思路:
考虑通过比较当前的1的数目来进行最小的数的修正。
先将D加1,然后计算出D的1的数目tot,这时候比较tot和s1,s2的大小,这时候有两种情况:
1、tot<s1,这时我需要增加1的数目,因为要最小,所以我从右开始找到一个0(位置假设为i),将D加上2^i。
2、tot>s2,这时我需要减少1的数目,所以我从右开始找到一个1,将D加上2^i。
如此循环上述过程,直到符合tot符合s1,s2的条件。
上面操作的原因是:我加上2^i,就是将那一位由1变为0或者由0变为1,而我是从右边开始寻找的,可以保证每次所做的改变都是最小的。同时我的D是一直增加的,所以当条件满足时,就是那个最小的。
代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
#define ll __int64
ll t,tot,s1,s2;
ll d[35],f;
ll getshu(ll x)
{
ll num=0;
t=0;
while(x)
{
d[t++]=x%2;
if(x%2)num++;
x=x/2;
}
return num;
}
ll quickpow(int a,int b)
{
ll ans=1;
while(b)
{
if(b%2)ans=ans*a;
a=a*a;
b=b/2;
}
return ans;
}
int main()
{
ll T,i,j,k,D,cases;
cases=0;
scanf("%I64d",&T);
while(T--)
{
f=0;
cases++;
memset(d,0,sizeof(d));
tot=0;
t=0;
scanf("%I64d%I64d%I64d",&D,&s1,&s2);
ll y=D;
y++;
while(1)
{
tot=getshu(y);
if(tot<s1)
{
for(i=0;i<t;i++)
{
if(d[i]==0){
y+=1<<i;
break;
}
}
}
else if(tot>s2)
{
for(i=0;i<t;i++)
{
if(d[i]==1)
{
y+=1<<i;
break;
}
}
}
else break;
}
printf("Case #%I64d: ",cases);
printf("%I64d\n",y);
}
return 0;
}