题目
As we known, data stored in the computers is in binary form. The problem we discuss now is about the positive integers and its binary form.
Given a positive integer I, you task is to find out an integer J, which is the minimum integer greater than I, and the number of '1’s in whose binary form is the same as that in the binary form of I.
For example, if “78” is given, we can write out its binary form, “1001110”. This binary form has 4 '1’s. The minimum integer, which is greater than “1001110” and also contains 4 '1’s, is “1010011”, i.e. “83”, so you should output “83”.
大意:给定一个数字,求解比这个数大,且二进制数中1的个数相同的数字
输入
One integer per line, which is I ( 1 ≤ I ≤ 1000000 ) I (1 \le I \le 1000000) I(1≤I≤1000000).
A line containing a number “ 0 0 0” terminates input, and this line need not be processed.
输出
One integer per line, which is J J J.
输入样例
1
2
3
4
78
0
输出样例
2
4
5
8
83
题目分析
本题主要分析了位运算的方法。首先可对输入的数查找其中最小的“ 01 01 01"位置,通过置换为” 10 10 10“来达到找出最小的比原数字大的,二进制中“ 1 1 1“的个数相同的数。
可以通过将数“ n n n”与其负数” − n -n −n“相与得到满足条件的最小数。即 x = n & ( − n ) x=n \& (-n) x=n&(−n)
例如: n = 0110110 n = 0110110 n=0110110,则 x = 2 x = 2 x=2;
当 x + n x+n x+n时,得 0111000 0111000 0111000.此时更变的” 01 01 01“之后的数全为 0 0 0.
要恢复少去的 1 1 1,可将 x + n x+n x+n与原数 n n n进行异或并且要移至低位(得到最小的数)
例如: ( x + n ) ⊕ n = 0001111 (x+n)\oplus n = 0001111 (x+n)⊕n=0001111,随后移位 ( x + n ) ⊕ n / x = 0000111 (x+n)\oplus n/x=0000111 (x+n)⊕n/x=0000111
但又因为 x + n x+n x+n将” 01 01 01“改成了” 10 10 10”,所以在异或时会多出2个” 1 1 1”.因此还需对结果右移两位。
最后,将得到的数与 x + n x+n x+n相加即可。即 x + n + ( ( ( x + n ) ⊕ n / x ) > > 2 ) x+n+(((x+n)\oplus n/x)>>2) x+n+(((x+n)⊕n/x)>>2); 得 0111001. 0111001. 0111001.
代码
#include <iostream>
using namespace std;
int main()
{
int n;
while(scanf("%d",&n)&&n){
int x = n & (-n);
int ans = x+n+((n^(x+n))/x>>2);
cout << ans<<endl;
}
return 0;
}