hdu5491 The Next(合肥网赛)

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
  
  
3 11 2 4 22 3 3 15 2 5

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

Source

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值