The Next
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 21 Accepted Submission(s): 10
Problem Description
Let
L
denote the number of 1s in integer
D
’s binary representation. Given two integers
S
1![]()
and
S
2![]()
, we call
D
a WYH number if
S
1
≤L≤S
2![]()
.
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.
With a given D
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
,
S
1![]()
, and
S
2![]()
, as described above. It is guaranteed that
0≤D<2
31![]()
and
D
is a WYH number.
Each test case consists of three integers D
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
Source
题意:L为D的二进制数中1的个数,然后求s1<=L<=s2的下一个D。
分析:把D的二进制数用数组存起来,然后记录末尾0(ret)和1(cnt)的个数,然后一位一位的找,比较水,只能想到这么暴力的方法,详解见代码。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
#define ll long long
#define CL(a) memset(a,0,sizeof(a))
ll ans;
int d,s1,s2;
int a[33];
int main ()
{
int T;
scanf ("%d",&T);
for (int ii=1; ii<=T; ii++)
{
scanf ("%d%d%d",&d,&s1,&s2);
ans=d;
printf ("Case #%d: ",ii);
int k=1,sum=0;
CL(a);
while (d)
{
a[k++]=d&1;
if (d&1) sum++;//总共有多少个1
d=d>>1;
}
bool flag=false;
int t,cnt=0,ret=0;
for (int i=1; i<=k; i++)
{
if (!flag&&a[i]==0) ret++;//末尾的0数
if (a[i]==1) {flag=true; cnt++;}//末尾的1数
if (flag&&a[i]==0) {t=i; break;}
}
//cout<<ret<<" "<<cnt<<" "<<t<<endl;
if (!ret)//末尾没0
{
if (sum-cnt>=s1-1) ans+=1;//如果总数减去末尾1的数量任在[s1-1, s2]内,直接加1
else //因为进位会多出一个1,所以是s1-1
{
int p=s1-(sum-cnt);//否则一位一位的补1
if (p==1) ans=d+1;
else
{
ans=ans+1;
p--;
while (p--)
{
ans=ans+(1<<p);
}
}
}
}
else//如果末尾有0
{
if (sum<s2)//总1数小于s2
{
ans=ans+1;
}
else//总1数等于s2
{
int g=ret;
while (g--)//把末尾的1变成1
ans=ans+(1<<g);
ans+=1;
int p=sum-cnt+1;
if (p<s1)//如果1的个数还小于s1,那就又变成的末尾没1的情况了
{
int h=s1-p;
while (h--)
{
ans=ans+(1<<h);
}
}
}
}
printf ("%I64d\n",ans);
}
return 0;
}