直接回答:必会清单:x & (x-1) 消去最低位的 1(数 1 的个数、判断是否 2 的幂——x & (x-1) == 0);lowbit = x & (-x) 取最低位的 1(树状数组的灵魂,负数的补码表示使然);x >> k & 1 取第 k 位;x | (1<<k) 置位、x & ~(1<<k) 清位、x ^ (1<<k) 翻转。异或三律(自反、交换、结合)支撑一整族题:找唯一出现一次的数、不用临时变量交换、缺失数字。

展开解析:lowbit 深入:树状数组里 i 管辖的区间长度就是 lowbit(i),父节点 = i + lowbit(i)、前缀查询沿 i -= lowbit(i) 下跳,O(log n) 支持单点改与前缀和——比线段树代码短得多。状态压缩(状压 DP):n ≤ 20 时用 int 的每一位表示元素选/不选,子集枚举 for (s = mask; s; s = (s-1) & mask) 是经典 O(3^n) 枚举所有子集的写法(内层等差数列求和得出),TSP、分配问题、棋盘覆盖的标配。工程向注意事项:语言差异——Java 的 >> 是算术右移、>>> 才是逻辑右移,Go/Rust 按类型符号性决定;位移量超过位宽是 UB 或被取模(Java 对 int 移位按 32 取模,i << 33 等于 i << 1,血坑);位运算优先级低于加减(x & 1 == 0 必须加括号)。性能认知:位运算快是附带的,真正的价值在内存(位图布隆过滤器)与表达力(权限位、协议标志位)。

追问方向:布隆过滤器的位数组如何选哈希与容量?(s-1) & mask 枚举子集为何不重不漏?

(约 480 字)