The Next
題目鏈接
題目大意
規定一種數叫做WYH數,其二進制中1的個數在s1,s2之間,現在給你一個WYH數,要你求比他大的WYH數中最小的一個(就是下一個WYH數)
題解
構造
其實這一題挺有意思的…
考慮比D大1的數D+1,先算出D+1中1的個數L,然後分情況討論:
如果L大於S2
因爲我們現在要減少1的個數,而且我們現在只能加,所以考慮二進制中的最後一個1,只有讓這一位向前進位,我們才能減少1的個數,所以對於這種情況,我們先找出最後一個1所在的位置,然後把該位的1向前進位。如果L小於S1
這個好說,我們從二進制的最右邊向左邊掃,把遇到的0全部變成1,知道滿足條件爲止。
代碼
#include <iostream>
#include <cstring>
#include <cstdio>
#define LL long long
using namespace std;
int T,s1,s2;
LL d;
int num(LL a)
{
int ans=0;
for (int i=0;i<32;i++) if ((1<<i)&a) ans++;
return ans;
}
int main()
{
int Case=1;
scanf("%d",&T);
while (T--)
{
scanf("%I64d%d%d",&d,&s1,&s2);
d++;
int l=num(d);
printf("Case #%d: ",Case++);
if (l>=s1 && l<=s2)
{
printf("%I64d\n",d);
continue ;
}
while (1)
{
if (l<s1)
{
for (int i=0;i<32;i++)
if (((1<<i)&d)==0)
{
d=d|(1<<i);
l++;
if (l==s1) break;
}
printf("%I64d\n",d);
break;
}
if (l>s2)
{
for (int i=0;i<32;i++) if ((1<<i)&d)
{
d+=(1<<i);
break;
}
l=num(d);
if (l>=s1 && l<=s2)
{
printf("%I64d\n",d);
break;
}
}
}
}
return 0;
}