位运算
1. 基础运算符
1.1 与运算(&)
- 含义:对应位都为 1 时结果位为 1,否则为 0
- 例:
6=1102, 5=1012
6 & 5=1002=4
1.2 或运算(|)
- 含义:对应位只要有一个为 1,结果位为 1
- 例:
6=1102, 5=1012
6 ∣ 5=1112=7
1.3 取反运算(~)
- 含义:0↔1(对所有位取反)
- 例:
5=000001012
∼5=111110102
(在常见补码表示下,这个结果对应十进制 −6)
1.4 异或运算(^)
- 含义:对应位不同为 1,相同为 0
- 例:
6=1102, 5=1012
6 ^ 5=0112=3
2. 移位运算符
2.1 左移(<<)
- 含义:整体向左移动,低位补 0
- 直观效果:相当于乘以 2k
- 例:
3=000000112
3≪2=000011002=12
2.2 右移(>>)
- 含义:整体向右移动,低位被舍弃
- 直观效果:相当于除以 2k 并向下取整
- 例:
13=000011012
13≫2=000000112=3
3. 位运算性质
3.1 异或性质(^)
- 交换律、结合律成立
- 自反:a⊕a=0
- 与 0 的关系:a⊕0=a
- 可逆性:(a⊕b)⊕b=a
3.2 与性质(&)
- 交换律、结合律成立
- 幂等:a & a=a
- 吸收:a & 0=0,a & 全1=a
- 递减:a & b≤min(a,b)
3.3 或性质(|)
- 交换律、结合律成立
- 幂等:a∣a=a
- 吸收:a∣0=a,a∣全1=全1
- 递增:a∣b≥max(a,b)
4. 位运算技巧
4.1 判断某一位是否为 1
- 思路:构造掩码 mask=1≪k,用与运算判断第 k 位是否为 1
- 表达式:x & (1≪k)
- 例:
x=13=11012
- 判断第 2 位:mask=01002
11012 & 01002=01002=0,所以第 2 位是 1
- 判断第 1 位:mask=00102
11012 & 00102=00002=0,所以第 1 位是 0
4.2 将某一位置 1 / 置 0 / 翻转
-
置 1:x ∣= (1≪k)
-
置 0:x &= ∼(1≪k)
-
翻转:x ^= (1≪k)
-
例:x=10=10102
(1) 置第 0 位为 1
k=0,1≪0=00012
x′=x ∣ (1≪0)=10102 ∣ 00012=10112=11
(2) 置第 1 位为 0
k=1,1≪1=00102,∼(1≪1)=∼00102=11012
x′=x & ∼(1≪1)=10102 & 11012=10002=8
(3) 翻转第 3 位(0↔1)
k=3,1≪3=10002
x′=x ^ (1≪3)=10102 ^ 10002=00102=2
4.3 找最低位的 1(lowbit)与删除最低位的 1
- lowbit:lowbit(x)=x & (−x)(提取最低位的 1 所代表的值)
- 删除最低位的 1:x & (x−1)
- 例:
x=12=11002
- lowbit(x)=01002 (=4)
- x & (x−1)=11002 & 10112=10002 (=8)
4.4 统计二进制中 1 的个数
- 方法:不断删除最低位的 1,删除次数就是 1 的个数
操作:反复执行 x &= (x−1)
- 例:
x=13=11012
1101→1100→1000→0000
共 3 次,所以 popcount(13)=3
4.5 判断是否为 2 的幂
- 结论:对 x>0,若 x & (x−1)=0,则 x 是 2 的幂
(2 的幂在二进制中只有一个 1)
- 例:
- 8=10002:8−1=7=01112,10002 & 01112=00002,是 2 的幂
- 12=11002:12−1=11=10112,11002 & 10112=10002=0,不是 2 的幂
4.6 用整数的二进制位表示集合及子集枚举
- 集合表示(状态压缩):用一个整数 mask 表示集合
- 第 i 位为 1:元素 i 在集合中
- 第 i 位为 0:元素 i 不在集合中
- 例:
有 4 个元素 {0,1,2,3},mask=13=11012
表示集合为 {0,2,3}(第 0,2,3 位为 1)
ex 子集枚举 / 超集枚举
设全集大小为 n,全集掩码 U=(1≪n)−1。
1) 子集枚举(枚举 mask 的所有子集 sub)
for (int sub = mask; ; sub = (sub - 1) & mask) {
if (sub == 0) break;
}
2) 超集枚举(枚举所有 sup⊇mask)
做法:先枚举可选位 free=U⊕mask 的子集 t,再令 sup=mask∣t。
int free = U ^ mask;
for (int t = free; ; t = (t - 1) & free) {
int sup = mask | t;
if (t == 0) break;
}
5. 常用函数
5.1 统计二进制中 1 的个数(popcount)
__builtin_popcount(x)
__builtin_popcountll(x)
5.2 末尾连续 0 的个数(ctz)
__builtin_ctz(x)
__builtin_ctzll(x)
- 注意:当 x=0 时结果未定义(调用前需保证 x=0)
5.3 前导连续 0 的个数(clz)
__builtin_clz(x)
__builtin_clzll(x)
- 注意:当 x=0 时结果未定义(调用前需保证 x=0)
5.4 最高位 1 的位置(0-based)
- 对 x>0:
pos = 31 - __builtin_clz(x)(32 位)
pos = 63 - __builtin_clzll(x)(64 位)
5.5 最低位 1 的位置(0-based)
- 对 x>0:
pos = __builtin_ctz(x)(32 位)
pos = __builtin_ctzll(x)(64 位)
【前置知识点】
1、进制转换
【思维导图】

【题目知识点分类】
