hdu5491 The Next(合肥网赛)

来源:互联网 发布:装备增幅数据 编辑:程序博客网 时间:2024/06/08 16:31

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 S1 and S2, we call D a WYH number if S1LS2.
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 (T300000).
Each test case consists of three integers D,S1, and S2, as described above. It is guaranteed that 0D<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
311 2 422 3 315 2 5

Sample Output
Case #1: 12Case #2: 25Case #3: 17

Source
2015 ACM/ICPC Asia Regional Hefei Online 

题意: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;}


0 0