题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5491
题目大意:
L 是整数 D 的二进制中 1 的个数,如果 s1 <= L <= s2,则称 D 是一个 WYH数。
现在给你一个整数 D 和 s1、s2,求比 D 大的下一个 WYH数是多少。
解题思路:
参考博文:http://blog.csdn.net/joyce__yin/article/details/48786131
从低位向高位考虑。
用数组 Num[] 来存 D 的二进制形式(从低位到高位),Sum[] 来存储二进制从高位到
当前位上 1 的个数。然后从低位到高位枚举 D 二进制出现 0 的位,如果该位为 0,
则将该位置为 1,该位之前的所有低位都置为 0。如果现在拥有的 1 的个数大于 s2,
则继续枚举出现 0 的位。如果现在拥有的 1 的个数在区间 [s1,s2] 之间,即为所求。
如果现在拥有的 1 的总数小于 s1,则从最低位开始,依此设置 1,直到总数等于 s1。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define LL __int64
using namespace std;
int Num[35],Sum[35];
int main()
{
int T,kase = 0;
LL d,s1,s2;
scanf("%d",&T);
while(T--)
{
scanf("%I64d%I64d%I64d",&d,&s1,&s2);
memset(Num,0,sizeof(Num));
memset(Sum,0,sizeof(Sum));
int Cnt = 0,Pos = 0;
LL n = d;
while(n)
{
if(n & 1)
{
Cnt++;
Num[Pos] = 1;
}
Pos++;
n >>= 1;
}
for(int i = Pos-1; i >= 0; --i)
{
Sum[i] = Sum[i] + Sum[i+1] + Num[i];
}
for(int i = 0; i <= Pos; ++i)
{
if(Num[i] == 0)
{
int Temp = Sum[i] + 1; //从最高位到当前位上 1 的个数
if(Temp > s2) //1 的个数大于 s2,继续枚举
continue;
LL Ans = 0;
int pos = 0;
while(Temp < s1) //1 的个数小于 s1,从最低位开始依次置为 1
{
Ans += pow(2,pos);
pos++;
Temp++;
}
//下边加上当前位到最高位上的二进制对对应值
Ans += pow(2,i);
for(int j = i+1; j < Pos; ++j)
{
Ans += Num[j]*pow(2,j);
}
printf("Case #%d: %I64d\n",++kase,Ans);
break;
}
}
}
return 0;
}