跳转至

位运算#
发布于2021-02-25
上次编辑2021-02-25

1
2
3
4
5
6
x = x & -x;         // 将除最低位的 1 之外的其余位置 0
x = x & (~(x - 1)); // 同上
x = x & (x - 1);    // 将最低位的 1 置 0
x = x & ~(1 << k);  // 将第 k (最低位为 0) 位置 0
x = x | (1 << k);   // 将第 k (最低位为 0) 位置 1
x = (x >> k) & 1;   // 获取第 k (最低位为 0) 位

连续 1 出现的最多次数

1
for (int i = 0; x; x &= (x >> 1), ++i);

遍历 x 的非空子集

1
for (int y = x; y; --y &= x);

最大值/最小值

1
2
3
// 若 a>=b,则 (1LL * a - b) >> 63 返回 0, ~(1LL * a - b) >> 63 返回 -1 即 0xffffffffffffffff
int max(int a, int b) { return b & ((1LL * a - b) >> 63) | a & (~(1LL * a - b) >> 63); }
int min(int a, int b) { return a & ((1LL * a - b) >> 63) | b & (~(1LL * a - b) >> 63); }

遍历元素个数为 N 的集合的所有子集

1
2
3
4
5
6
7
for (int i = 0; i < (1 << N); ++i) {
    for (int j = 0; j < N; ++j) {
        if ((i >> j) & 1) {
            // Code here
        }
    }
}

遍历元素个数为 N 的集合的元素个数为 K 的子集 (字典序生成) (Gosper’s hack)

1
2
3
4
5
6
7
int n, k;
int x = (1 << k) - 1, c, r;

while (x < (1 << n)) {
    // cout << x << '\n';
    c = x & -x, r = x + c, x = (((r ^ x) >> 2) / c) | r;
}

例题#

返回顶部

在手机上阅读