Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2706 Accepted Submission(s): 961
Problem Description
Let L denote the number of 1s in integer D’s binary representation. Given two integers S1 and S2, we call D a WYH number if S1≤L≤S2.
With a given D, we would like to find the next WYH number Y, which is JUST larger than D. In other words, Y is the smallest WYH number among the numbers larger than D. Please write a program to solve this problem.
Input
The first line of input contains a number T indicating the number of test cases (T≤300000).
Each test case consists of three integers D, S1, and S2, as described above. It is guaranteed that 0≤D<231 and D is a WYH number.
Output
For each test case, output a single line consisting of “Case #X: Y”. X is the test case number starting from 1. Y is the next WYH number.
Sample Input
3
11 2 4
22 3 3
15 2 5
Sample Output
Case #1: 12
Case #2: 25
Case #3: 17
考虑比D大1的数D+1,先算出D+1中1的个数L,然后分情况讨论:
如果L大于S2
因为我们现在要减少1的个数,而且我们现在只能加,所以考虑二进制中的最后一个1,只有让这一位向前进位,我们才能减少1的个数,所以对于这种情况,我们先找出最后一个1所在的位置,然后把该位的1向前进位。
如果L小于S1
这个好说,我们从二进制的最右边向左边扫,把遇到的0全部变成1,知道满足条件为止。
#include<iostream>
using namespace std;
#define ll long long
using namespace std;
int is_1s(ll a)
{
int ans = 0;
for (int i = 0; i < 32; i++)
if ((1 << i)&a)
ans++;
return ans;
}
int main()
{
int t;
ll d;
int s1, s2;
cin >> t;
int Case = 1;
while (t--)
{
scanf("%lld%d%d", &d, &s1, &s2);
//cin >> d >> s1 >> s2;
d++;
int len = is_1s(d);
if (len >= s1&&len <= s2)
{
printf("Case #%d: %lld\n", Case++, d);
//cout << "Case #" << Case++ << ": " << d << endl;
continue;
}
while (1)
{
if (len < s1)
{
for(int i=0;i<32;i++)
if (((1 << i)&d) == 0)
{
d = d | (1 << i);
len++;
if(len==s1)
break;
}
printf("Case #%d: %lld\n", Case++, d);
//cout << "Case #" << Case++ << ": " << d << endl;
break;
}
if (len > s2)
{
for(int i=0;i<32;i++)
if ((1 << i)&d)
{
d += (1 << i);
break;
}
len = is_1s(d);
if (len>=s1&&len<=s2)
{
printf("Case #%d: %lld\n", Case++, d);
//cout << "Case #" << Case++ << ": " << d << endl;
break;
}
}
}
}
}