0. 前言
位运算的东西很零散,模板不太好整理,大约见到了就会及时添加进来吧,顺便附上一道 OJ
练下手。
1. n >> k 移位
常见问题:n
的二进制表示中的第 k
位是几?
解答: n >> k & 1
2. lowbit(x)
lowbit(x)
操作,返回 x
的二进制表示的最后一位 1。
lowbit(x)
也是树状数组的基本操作。
因为 -x
在计算机以补码存储为 -x = ~x + 1
,则 x & -x = x & ( ~x + 1)
x = 1010....10000
~x = 0101....01111
~x + 1 = 0101....10000
则:x & -x = x & ( ~x + 1) = 0000....10000 即返回了x 的最后一位 1
代码如下:
#include <iostream>
using namespace std;
int lowbit(int x) {
return x & -x;
}
int main() {
int n, a, res;
scanf("%d", &n);
while (n --) {
res = 0;
scanf("%d", &a);
while (a) {
a -= lowbit(a);
++res;
}
printf("%d ", res);
}
return 0;
}
2. n &= n - 1
n &= n - 1
操作,消除 n
的二进制表示的最后一位1。
这个方法貌似有个帅气的英文名字,忘掉了,可以用它很快的统计二进制中 1 出现的次数,因为它可以跳过连续的 0。
x = 1010....10000
x - 1 = 1010....01111
则:n &= n - 1 = 1010....00000 即消除了 x 的最后一位 1,且只用了一次操作
代码如下:
#include <iostream>
using namespace std;
const int N = 1e5+5;
int n;
int a[N];
int main() {
cin >> n;
while (n --) {
int t, cnt = 0;
cin >> t;
while (t) {
++cnt;
t &= t - 1;
}
cout << cnt << ' ';
}
return 0;
}