给定一个正整数 N,求最小的、比 N 大的正整数 M,使得 M 与 N 的二进制表示中有相同数目的1。
举个例子,假如给定的 N 为 78,其二进制表示为 1001110,包含 4 个 1 ,那么最小的比 N 大的并且二进制表示中只包含 4 个 1 的数是 83 ,其二进制是 1010011,因此 83 就是答案。
输入输出格式
输入格式
输入若干行,每行一个数 n,输入"0"结束。
输出格式
输出若干行对应的值。
输入输出样例1
输入
1
2
3
4
78
0
输出
2
4
5
8
83
说明提示
1≤n≤10
6
/*
一次从下一个数开始递增枚举
计算给定十进制数的二进制
判断两个数二进制是不是相等
*/
#include <iostream>
using namespace std;
//计算给定十进制正整数转换为二进制中含有的1
//代码原理进制转换中是循环逆向取余数法
int countOnes(int N){
int res=0;
while(N){
if(N%2==1)
res++;
N/=2;
}
return res;//记录十进制数转为二进制数中有多少位1
}
/*
//计算一个数的二进制表示中 1 的个数
//代码的原理是位运算
int countOnes(int num) {
int count = 0; // 用于记录二进制表示中 1 的个数,初始化为 0
while (num) { // 当 num 不为 0 时,继续循环,因为当 num 变为 0 时,说明已经检查完所有的位
count += num & 1; // 使用按位与运算(&)回检查 num对应的二进制数 的最低位(最靠右边)是否为 1
num >>= 1; // 将 num 右移一位,相当于去掉最低位,以便检查下一位(也就是之前的靠左一位代替成了的现在最低位)
//比如 二进制数100 通过>>左移 变成了10
}
return count; // 返回统计得到的 1 的个数
}
//按照位运算中的&&(按位与)||(按位或)···
//这算一种技巧,希望记住,我想信万千智慧始于记忆,理解也是为了更好的记忆
*/
//判断两个数二进制含有的1是不是相等
int findNextNum(int N){
int target=countOnes(N);
int i=N+1;
while(1){
//死循环并不是一无是处,有点像简单枚举
//从贪心算法角度解释,就是现解决一个小问题就算一次小成功,知道将所有小问题都解决,就算完成任务了
if(countOnes(i)==target)
break;//找到了,不会再执行下一语句,直接跳出
i++;
}
return i;
}
int main(){
int num;
while(cin>>num&&num!=0)
cout<<findNextNum(num)<<endl;
return 0;
}