zoukankan      html  css  js  c++  java
  • HDU 5491 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 S1≤L≤S2.
    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, S1, and S2, as described above. It is guaranteed that 0≤D<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
    
     2015 ACM/ICPC Asia Regional Hefei Online 

    这道题在比赛的时候我就是用的这个方法,但是一直超时。后来重新写了一遍,用了G++过了。

    思路:

    从小到大找必定超,我看限制条件一的个数是0~32差不多,这么个循环是不会超时的。我就从i->s1~s2循环,里面找一的个数为i的。

    这里因为要i个1,然后又要比L大那么把第i个1前移一位。

    下面这里分两个情况:

    以需要3个1为例

    ①11011->11100

    ②10111->11001如果进位了,就在末尾补1.

    还有一种情况就是找不到第i个1:就从后往前变0为1,直到满足i个1.

    然后去每种1个数的最小值。

    证明正确性:

    试想要i个1那么不够的话还要比他大是不是往后补就行,因为1放在越后面越小。

    要是够,因为要比他大,这里可知1的个数比需要的多。我们就要删掉1,那么删哪些呢?到第i个1为止,你后面在怎么变①后面1变少,数值变小,不行②1变多,我们现在要删掉1,不行;

    所以后面的都不行,那么第i个1要进位了。然后进位完,1不够了,最小就往最后面补。

    #include<stdio.h>
    int main()
    {
        int T,s1,s2;
        __int64 L,p;
        int cas=0;
    
        scanf("%d",&T);
        while(T--)
        {
            scanf("%I64d%d%d",&L,&s1,&s2);
             p=(__int64)1<<40;
            
            if(L==0&&s1==0&&s2==0){
                printf("Case #%d: 0
    ",++cas);
            continue;
            }
            int flag=0;
            __int64 t;
            for(int i=s1;i<=s2;i++)
            {
                int s=0,f=0;
                t=(__int64)0;
                for(int j=32;j>=0;j--)
                {
                    if(L&((__int64)1<<j))s++;
                    if(s==i)
                    {
                        int z,k;
                        for(k=j;k<=32;k++)
                        {if(L&((__int64)1<<k));
                        else {
                            t|=(__int64)1<<k;
                        break;
                        }
                        }
                        
                        z=1;
                         for(int kk=k+1;kk<=32;kk++)
                         {
                             if(L&((__int64)1<<kk))t|=(__int64)1<<kk,z++;
                         }
                         z=i-z;
                         for(k=0;k<=32&&z>0;k++)t|=(__int64)1<<k,z--;
                         p=p>t?t:p; 
                    
                    f=1;
                    break;
                    }     
                }
                if(!f)
                {
                    s=i-s;
                    t=L;
                    for(int k=0;k<=32&&s>0;k++){
                    if(L&((__int64)1<<k));
                    else t|=(__int64)1<<k,s--;
                    }
                    p=p>t?t:p; 
                    
                }
                
            }
            printf("Case #%d: %I64d
    ",++cas,p);
        }
    } 
  • 相关阅读:
    演示Eclipse插件实现代码提示和补全
    重拾《 两周自制脚本语言 》- Eclipse插件实现语法高亮
    Kindle Windows版本 中文字体修改工具
    MD5加密算法原理及实现
    Spring boot 发送邮件示例
    ubuntu下svn的命令使用
    数据库的分区、分表、分库、分片的简介
    Vue 入门之目录结构介绍
    MQTT简单介绍与实现
    SVN使用规范
  • 原文地址:https://www.cnblogs.com/newadi/p/4860316.html
Copyright © 2011-2022 走看看