【题目描述】
给出一个整数,输出比其大的第一个数,要求输出的数二进制表示和原数二进制表示下1的个数相同。
【题目链接】
http://noi.openjudge.cn/ch0406/1455/
【算法】
1、自己想的:设原数为n,从lowbit(n)开始左移找到第一个0的位置,同时记录该位置之前1的个数,将该位置置1,然后把1全堆在最后;如果找不到该位置,则该数是形如111100000...的样式,故将其左移一位,再把1堆在最后。感觉不够清晰。
2、借鉴网上题解,比我清晰很多:直接给原数加上lowbit(n),再把1堆在最后,结束。。。而且堆在最后也可以简洁的用位运算:(n^(n+lowbit(n)))/lowbit(n)>>2(原来lowbit(n)前有x个1,异或之后有x+1个1,应该堆x-1个1,所以右移两位)。。。不过用时都是2ms。。。时间都耗在cin上了吧。。。。
【代码1】
1 #include <bits/stdc++.h> 2 using namespace std; 3 int a,b,rec,num,ans; 4 int main() 5 { 6 while(cin>>a&&a) { 7 rec=num=0; 8 b=a&-a; 9 while(b<=a&&!rec) { 10 if(!(a&b)) rec=b; 11 else num++; 12 b<<=1; 13 } 14 num--; 15 if(!rec) { 16 ans=b+(1<<num)-1; 17 } 18 else { 19 rec=-rec; 20 ans=a&rec; 21 ans+=(-rec); 22 ans+=(1<<num)-1; 23 } 24 cout<<ans<<endl; 25 } 26 return 0; 27 }
【代码2】
#include <bits/stdc++.h> using namespace std; int a; int main() { while(cin>>a&&a) { cout<<a+(a&-a)+((a^(a+(a&-a)))/(a&-a)>>2)<<endl; } return 0; }