NYOJ 412 Same binary weight(bitset位运算)

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
110101101
01
1718
11010110110
4
0100
8
1000
7
0111
11
1011
12
01100
17
10001
555555
10000111101000100011
555557
10000111101000100101

从表中可以找到一个规律就是将二进制的第一个出现的01变成10然后再将01之后的所有的1都移到最右边。

上代码:

#include<map>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<sstream>
#include<set>
#include<stack>
#include <bitset>//这里要用到bitset函数所以一定要加这个头文件
using namespace std;
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        bitset<32>bt(n);//首先将n变成二进制并保留32位
        int count=0,flag;
        for(int i=0;i<32;i++)
        {
            if(bt[i]==1)
            {
                count++;//统计在找到01之前有多少1以便于后面将01后面的1全部移到最右边
            }
            if(bt[i]==1&&bt[i+1]==0)//找到第一个01将其变成10并用flag标记
            {
                bt[i]=0;
                bt[i+1]=1;
                flag=i;
                break;
            }
        }
        for(int i=0;i<count-1;i++)//01之后的count-1个1移到最右边
        {
            bt[i]=1;
        }
        for(int i=count-1;i<flag;i++)//其余的都变成0
        {
            bt[i]=0;
        }
        printf("%d\n",bt.to_ulong());//将二进制变成十进制
    }
    return 0;
}


这里用到了两个函数bitset函数将十进制变成二进制,bt.to_ulong()将二进制变成十进制

这里还可以用位运算首先介绍一下按位与&和按位或|

按位与&就是当对应的两个二进制位均为1时结果才为1,否则的话为0.

按位或|就是对应的两个二进制位只要有一个为1结果就为1,全为0结果就为0

然后是这道题的算法:

<p style="margin: 10px auto; padding-top: 0px; padding-bottom: 0px; line-height: 19.5px; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(254, 254, 242);">1. 约定 x 是输入的 N,如 x = 1717,则 -x = -1717,二进制中 -x = -1717(1001 0100 1011 原码取反加一)</p><p style="margin: 10px auto; padding-top: 0px; padding-bottom: 0px; line-height: 19.5px; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(254, 254, 242);">2. 令 b = x & (-x),得到 x 中最后一个 “1” 的位置</p><p style="margin: 10px auto; padding-top: 0px; padding-bottom: 0px; line-height: 19.5px; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(254, 254, 242);">3. 令 t = x + b, 产生进位,实现 “01” 改变为 “10”</p><p style="margin: 10px auto; padding-top: 0px; padding-bottom: 0px; line-height: 19.5px; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(254, 254, 242);">4. 令 s = t ^ x, 得到进位过程中发生变动的位</p><p style="margin: 10px auto; padding-top: 0px; padding-bottom: 0px; line-height: 19.5px; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(254, 254, 242);">5.  (s >> 2),“10” -》 "10" 后这两位就不要再去改变它们了,所以右移 2 位(去掉这两位)</p><p style="margin: 10px auto; padding-top: 0px; padding-bottom: 0px; line-height: 19.5px; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(254, 254, 242);">6. 令 k = (s >> 2)/ b,除去“01” -》 “10”这两位外,将“01”以后至最后一个“1“(包含最后一个”1“)之间的所有”1“移动至最后,原理见下</p><p style="margin: 10px auto; padding-top: 0px; padding-bottom: 0px; line-height: 19.5px; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(254, 254, 242);">7. 那么最后的结果就是 t | k</p><p style="margin: 10px auto; padding-top: 0px; padding-bottom: 0px; line-height: 19.5px; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: rgb(254, 254, 242);"> </p>具体代码自己想一想吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值