Lowbit运算
lowbit运算
lowbit运算的结果是返回一个数的二进形式下最后一个1及之后的二进制数。
实现形式(x为一个整数):
x&(-x)
为什么这样就能实现呢?
首先我们要知道在C++中,关于负数的加减的储存离不开补码的概念。
**
什么是补码?
负数补码的值是在原码的基础上先取反后+1(正数的补码就是它本身),比如:
-1
源码:10000001
反码:11111110
补码:11111111
+1的原码、反码和补码都是:
00000001
那么我们实现1+(-1)时,实际上是他们的补码相加,自然就是00000000
**
现在我们来解释x&(-x)
x&(-x) = x&(~x+1)
大家应该能看得懂上面的等式吧,那么我们假设x为这样一个数:
101110101000...(无序的杂乱无章的0和1)1(最后一个1)0000....(之后全是0)
那么对它取反是:
010001010111...(与原码相反的无序的杂乱无章的0和1)0(最后一个1对应的0)1111....(之后全是1)
那么很容易想到,我们对反码+1后,进位停止于从右往左数的第一个0,也就是说以这个0为界限,它左边的二进制数不会发生变化,而右边包括它自己将会变回与反码相同的数:
010001010111...(与原码相反的无序的杂乱无章的0和1)1(最后一个1)0000....(之后全是0)
这样,当我们用其与原码进行 &(与) 运算时,前面的的部分会因为与原码正好相反而全部得出0,后一部分会因为与原码完全相同而保留下来,从而得出x的二进制情况下最后一个1及之后的二进制数。
lowbit的应用
最常见的应用就是统计x二进制数中1的个数,即当我们每次都用x减去它的lowbit值,并且count++,直到x=0时,我们就能计算出x二进制数中1的个数: 核心代码:
while (n != 0)
{
lowbit = n & (-n);
n -= lowbit;
++count;
}
#include <iostream>
int main()
{
int n,q;
std::cin >> q;
int lowbit, count = 0;
while (q--)
{
std::cin >> n;
while (n != 0)
{
lowbit = n & (-n);
n -= lowbit;
++count;
}
std::cout << count<<" ";
count = 0;
}
}