HDU 5491 The Next 构造(2015 ACM/ICPC Asia Regional Hefei Online)

本文介绍了一种使用Lowbit技巧解决特定二进制位数问题的方法。通过实例解析了如何构造满足条件的最小数值,以及如何通过代码实现这一过程。

题意】:

给你一个D( 0D<231 ),保证D的二进制中1的数量在s1和s2之间

然后让你求一个最小的数,使得这个数的二进制数量大于等于s1,小于等于s2,且大于 d

【思路】虽然是比赛时候的一道水题,但是开始看到的时候并没有想到好的思路,最后还是学弟强行过掉,今天突然想到了可以用lowbit来求

首先看到D的范围是很大的,那么如何 构造呢?

这里举个例子:比如11,二进制表示(1011),取11+1=12,二进制表示(1100)s1=2,那么我们要做的就是考虑构造数的范围,如果当前数的s1 小于左区间的值,我们要做的就是从最后一个0出现的位置添加1,也就是从右到左,我们发现对12取按位反后得到(0011),取一次lowbit得到从右往左第一个1的位置是1,那么我们就把12+1=13(1101),相当于12的十进制加一,也等于12的二进制多添了一个1,这样是构造小于左区间的,那么如果大于左区间,又要满足条件,即取大于D的最小值,不难发现,只要加上lowbit(d)即可

代码:

[cpp]  view plain copy
  1. /*   
  2. * Problem: HDU No.5491 
  3. * Running time: 499MS   
  4. * Complier: G++   
  5. * Author: javaherongwei  
  6. * Create Time:  8:47 2015/9/28 星期一 
  7. */    
  8. #include <bits/stdc++.h>  
  9. using namespace std;  
  10. typedef long long LL;  
  11. inline LL read(){  
  12.     int  c=0,f=1;  
  13.     char ch=getchar();  
  14.     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}  
  15.     while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}  
  16.     return c*f;  
  17. }  
  18. LL bitwei(LL x){  
  19.     LL s=0;  
  20.     while(x){  
  21.         if(x%2) s++;  
  22.         x/=2;  
  23.     }  
  24.     return s;  
  25. }  
  26. LL bitwei2(LL x){  
  27.     x = (x&0x55555555) + ((x>>1) & 0x55555555);  
  28.     x = (x&0x33333333) + ((x>>2) & 0x33333333);  
  29.     x = (x&0x0F0F0F0F) + ((x>>4) & 0x0F0F0F0F);  
  30.     x = (x&0x00FF00FF) + ((x>>8) & 0x00FF00FF);  
  31.     x = (x&0x0000FFFF) + ((x>>16) & 0x0000FFFF);  
  32.     return x;  
  33. }  
  34.   
  35. LL lowbit(LL x){  
  36.     return x&(-x);  
  37. }  
  38. int main()  
  39. {  
  40.     int t,tot=1;t=read();  
  41.     while(t--){  
  42.         LL d,s1,s2;  
  43.         d=read();s1=read();s2=read();d++;  
  44.         LL len=bitwei2(d);  
  45.         while(!(len>=s1&&len<=s2)){  
  46.             if(len<s1) d+=lowbit(~d);  
  47.             else d+=lowbit(d);  
  48.             len=bitwei2(d);  
  49.         }  
  50.         printf("Case #%d: ",tot++);  
  51.         printf("%lld\n",d);  
  52.     }  
  53.     return 0;  
  54. }  
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值