[思路题] hdu 5491 The Next

来源:互联网 发布:r230搓纸轮 淘宝 编辑:程序博客网 时间:2024/04/29 03:23

题意:

找一个最小的比D大的且二进制数含有1的个数在 s1~s2 之间。

保证输出的D的二进制数也在s1~s2之间

思路:

因为D符合题意,所以我们先考虑如果D%2==0,那么加个1会不会超过s2,不会的话 答案就是D+1

那么如果会或者不是1,那么肯定D要发生进位了。

因为要比D大,所以我们把D二进制最后一个1之前的第一个0变成1,这之后都为0

然后从最后开始补1直到符合s1为止


这题有个坑点就是

2^30 1 1

答案是2^31

然而这个数超int,需要处理。

代码:

#include"cstdlib"#include"cstdio"#include"cstring"#include"cmath"#include"queue"#include"algorithm"#include"iostream"#include"map"#include"stack"#define eps 1e-8using namespace std;#define ll __int64#define MAXN 200004int main(){    int t,cas=1;    cin>>t;    while(t--)    {        ll d,ans=0;        int s1,s2;        scanf("%I64d%d%d",&d,&s1,&s2);        int cnt=0;        for(int i=0; i<=32; i++)        {            if((1LL<<i)&d) cnt++;        }        if(d%2==0 && cnt<s2)        {            printf("Case #%d: %I64d\n",cas++,d+1);            continue;        }        int j;        for(j=0; j<=32; j++) if((1LL<<j)&d) break;        for(j=j+1; j<=32; j++) if(!((1LL<<j)&d)) break;        d+=(1LL<<j);        int sum=0;        for(int i=33; i>=j; i--)        {            if((1LL<<i)&d)            {                ans+=(1LL<<i);                sum++;            }        }        for(int i=0; i<s1-sum; i++) ans+=(1LL<<i);        printf("Case #%d: %I64d\n",cas++,ans);    }    return 0;}


0 0
原创粉丝点击