poj2453学习

题目翻译:一个数字x的二进制有a个1,求第一个比x大的数字,让1的数量也是a

思路:从低位到高位,找到第一个01,改成10,并把10后面的所有的1移到低位就可以了

比如1001110

第一个01是第3位和第4位的(从0开始数),变成10,1010110,10后面有2个1,移到低位就是1010011,这个就是答案了

具体解题方法,x=n&(-n)可以获得最低位的1

因为,如果1是第0位,反码就是取反,就变成了0,补码再加1就是最低位的1,

如果1后面有多个0(100000),反码取反就是0后面多个1(011111),补码+1之后会进位到第一个1(100000),

例如n=0100110

-n原码是1100110

-n反码是1011001,

-n补码是1011010,

n&(-n)=10

得到了最低位的1,我们要把01变成10,具体做法就是n+x

因为如果原本01000这样的,那么n+x就会进位成10000,

如果原本是0111110这样的,那么n+x就会进位成1000000

例如n=0100110,n+x就是0101000

将01变成10之后我们也把10后面的1都变成了0,我们要补回来,这时候我们想到了异或,相同为0,不同为1,n^(n+x)这时候可以获得原本是0由n+x变成1的0,

例如n=0100110,n+x变成了0101000,第1位的1变成了0,n^(n+x)会变成0001110

这时候吧所有的1移到低位,也就是n^(n+x)/x

例如0001110,或变成111,

由于之前异或的时候01和10异或会变成11,也就是多了2个1,这时候我们右移两位(n^(n+x))/x>>2,这样就可以吧10后面的1都移到低位

所以答案就是x=n&(-n),result=n+x+(n^(n+x))/x>>2;

ac代码

#include<stdio.h>
int main(){
	int n,x;
	while(scanf("%d",&n)&&n){
		x=n&(-n);
		printf("%d\n", n + x + ((n ^ (n + x)) / x >> 2));
	}
	return 0;
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nightmare004

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值