HDU 5491 The Next 贪心

The Next

Time Limit: 1 Sec  

Memory Limit: 256 MB

题目连接

http://acm.hdu.edu.cn/showproblem.php?pid=5491

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

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);
        }
    }
}

 

    原文作者:qscqesze
    原文地址: https://www.cnblogs.com/qscqesze/p/4842500.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞