您的位置:首页 > 其它

hdu5491 The Next(合肥网赛)

2015-09-27 18:08 288 查看

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.

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.

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
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: