题目来源:http://acm.nyist.net/JudgeOnline/problem.php?pid=412

Same binary weight

时间限制:300 ms  |  内存限制:65535 KB
难度:3
 
描述

The binary weight of a positive  integer is the number of 1's in its binary representation.for example,the decmial number 1 has a binary weight of 1,and the decimal number 1717 (which is 11010110101 in binary) has a binary weight of 7.Give a positive integer N,return the smallest integer greater than N that has the same binary weight as N.N will be between 1 and 1000000000,inclusive,the result is guaranteed to fit in a signed 32-bit interget.

 
输入
The input has multicases and each case contains a integer N.
输出
For each case,output the smallest integer greater than N that has the same binary weight as N.
样例输入
1717
4
7
12
555555
样例输出
1718
8
11
17
555557

分析:

先看看这几个例子:

1717(0110 1011 0101),下一位是 1718(0110 1011 0110

767(0010 1111 1111),下一位是 895(0011 0111 1111)

348(0001 0101 1100),下一位是 355(0001 0110 0011

其中不难发现一个规律,从右起的第一个“01”改变为“10”,并且在“01”的后面所有的“1”都移动至最后,事实上,这个就是解题的关键点,那么整个问题求解的核心就转移到这两个子问题:

1. 将右起第一个“01”,改变为“10”

2. 将该“01”后面的所有“1”移动至最后

位运算的代码:

#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <iostream>
#include <vector>
#include<string>
#include<cstring>
#include<string.h>
#include<set>
#include<queue>
#include<stack>
#include<map>
using namespace std;
typedef long long LL;

int main()
{
    int n;
    while(cin>>n)
    {
       int b=n&(-n);// 得到n中最后一个‘1’到最后的值
       int t=n+b; // 产生进位, 实现‘01’ 变成 ‘10’
       int s=t^n;   // 得到进位中发生变动的位
       int k=(s>>2)/b;//先 ‘01’->'10'发生后不要去改变这两位,所以右移2位,然后将‘01’以后的‘1’移动到最后。
       int n=t|k; // 最后的结果就是t|k
       cout<<n<<endl;
    }
    return 0;
}

stl 模板代码如下:

 

#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <iostream>
#include <vector>
#include<string>
#include<cstring>
#include<string.h>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<bitset>
using namespace std;
typedef long long LL;

void trans(int x)
{

}
int main()
{
    int n;
    while(cin>>n)
    {
        bitset<32>q; // 32位容器
        int i=0;
        while(n)// 将n表示成二进制
        {
            if(n&1)
                q.set(i);
            i++;
            n>>=1;
        }
       // cout<<q.to_string()<<endl;
        int len=i;
        int counter=0;
        for(int j=0;j<len;j++)
        {
            if(q.test(j))  // 测试j位是否为1
            {
                counter++;  // 记录在首个‘01’之前有多少个1
                q.reset(j);   // 将j位 置 0
                if(!q.test(j+1)) // 找到‘01’首个,break
                {
                    q.set(j+1);  
                    break;
                }
            }
        }
        for(int j=0;j<counter-1;j++) // 把1移到低位
            q.set(j);
        cout<<q.to_ulong()<<endl; //返回 无符号长整型数 

    }

    return 0;
}