HDU 5491.The Next【2015 ACM/ICPC Asia Regional Hefei Online】【方法】【9月30】

本文介绍了一种高效算法,用于解决寻找大于给定整数D的下一个WYH数的问题,即二进制中1的个数位于指定范围内的最小整数。文章提供了两种实现思路,一种为直接搜索法,另一种则是优化后的算法,后者避免了超时问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The Next

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 DS1, 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
 
这个题直接爆搜找是会超时的。方法:找到二进制1的个数比s1小的数,然后最小位往前是0的变1,直到1的个数等于s1。代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
    int T,kase=1;
    scanf("%d",&T);
    while(T--){
        long long D,s1,s2,cnt;
        scanf("%lld%lld%lld",&D,&s1,&s2);
        for(long long i=D+1;;i++){
            long long n=i,f[100]={0},t=0;
            cnt=0;
            while(n){
                f[t++]=n%2;
                n/=2;
                if(f[t-1]==1) cnt++;
            }
            if(cnt>=s1&&cnt<=s2){//符合题意
                printf("Case #%d: %lld\n",kase++,i);
                break;
            }
            else if(cnt<s1){//可以变
                t=0;
                while(cnt<s1){
                    if(f[t]==0){
                        cnt++;
                        f[t]=1;
                    }
                    t++;
                }
                long long sum=0,x=1;
                for(int j=0;j<100;j++){
                    sum+=(f[j]*x);
                    x*=2;
                }
                printf("Case #%d: %lld\n",kase++,sum);
                break;
            }
        }
    }
    return 0;
}
然后是爆搜程序,可以拿去对拍:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int main(){
    int T,kase=1;
    scanf("%d",&T);
    while(T--){
        int D,s1,s2;
        scanf("%d%d%d",&D,&s1,&s2);
        for(int i=D+1;;i++){
            int n=i,cnt=0;
            while(n){
                if(n%2==1) cnt++;
                n/=2;
            }
            if(cnt>=s1&&cnt<=s2){
                printf("Case #%d: %d\n",kase++,i);
                break;
            }
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值