HDU 5491 The Next 贪心
The Next
Time Limit: 1 Sec
Memory Limit: 256 MB
题目连接
http://acm.hdu.edu.cn/showproblem.php?pid=5491Description
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
HINT
题意
给你一个D,保证D的二进制中1的数量在s1和s2之间
然后让你求一个最小的数,使得这个数的二进制数量大于等于s1,小于等于s2,且大于 d
题解:
首先,这道题会爆int
我们首先想一想,只要d左移动一位,那么这个数一定是符合的,所以就只用在d*2到d+1里面去找就好了
我瞎想了几个贪心策略,然后取的最优解……
1.看这个数+1合不合法
2.这个数找到最右边的0,把这个0变成1之后,把这个1右边的1都尽量变成0
代码:
//qscqesze #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <bitset> #include <vector> #include <sstream> #include <queue> #include <typeinfo> #include <fstream> #include <map> #include <stack> typedef long long ll; using namespace std; //freopen("D.in","r",stdin); //freopen("D.out","w",stdout); #define sspeed ios_base::sync_with_stdio(0);cin.tie(0) #define maxn 300006 #define mod 1000000007 #define eps 1e-9 #define e exp(1.0) #define PI acos(-1) const double EP = 1E-10 ; int Num; //const int inf=0x7fffffff; const ll inf=999999999; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } //************************************************************************************* int get(ll x) { int c =0 ; // 计数器 while (x >0) { if((x &1) ==1) // 当前位是1 c++; ; // 计数器加1 x >>=1 ; // 移位 } return c ; } ll change(ll x,int num) { for(int i=0;i<132;i++) { if((x&(1LL<<i))==0) { x|=(1LL<<i); num--; } if(num==0) break; } return x; } ll change2(ll x,int K,int s1,ll P) { int l =0; for(int i=0;i<132;i++) { if((x&(1LL<<i))==0) { x|=(1LL<<i); l = i; break; } } int num = K+1; for(int i = l-1;i>=0;i--) { x-=(1LL<<i); num--; if(num==s1) break; } if(x>P*2)return P; return x; } int main() { int t;scanf("%d",&t); for(int cas = 1;cas <= t;cas ++) { ll a=read(),s1=read(),s2=read(); ll ans = a+1; printf("Case #%d: ",cas); int len = get(ans); if(len<=s2&&len>=s1) { printf("%I64d\n",ans); continue; } if(len<s1) { printf("%I64d\n",change(ans,s1-len)); continue; } if(len>s2) { while(len>s2) { ans = change2(ans,len,s1,a); len = get(ans); } printf("%I64d\n",ans); } } }