Bit Manipulation
Every integer in your computer is stored as a row of light switches — each switch is a bit, either on (1) or off (0). Bit manipulation means reaching in and flipping individual switches directly, without going through the slow machinery of arithmetic.
Why bother? Because these operations run in a single CPU clock cycle — literally the fastest thing a computer can do. Many tricks that look like they'd take \(O(n)\) work collapse to \(O(1)\) with the right combination of switches.
The six basic operations
AND (&): bit is 1 only if both inputs have 1. Use it to mask (isolate) specific bits.
OR (|): bit is 1 if either input has 1. Use it to set specific bits.
XOR (^): bit is 1 if inputs differ. Use it to toggle bits or detect differences.
NOT (~): flips all bits. In two's complement: ~x = −x − 1.
Left shift (<< k): multiply by 2^k (shift bits left, pad with zeros).
Right shift (>> k): divide by 2^k (shift right; arithmetic shift preserves sign).
Essential tricks
Check if n is a power of 2: n & (n−1) == 0 (and n > 0). A power of 2 has exactly one bit set. Subtracting 1 flips all bits below it and clears the top bit. AND gives 0.
Isolate the lowest set bit: n & (−n). In two's complement, −n = ~n + 1. The carry propagates through trailing zeros, stopping at the lowest 1-bit — which survives the AND.
Clear the lowest set bit: n & (n−1). This clears exactly one bit per call — the basis of Brian Kernighan's popcount algorithm.
XOR superpowers
Swap without a temp variable: a ^= b; b ^= a; a ^= b. Works because XOR is its own inverse: (a^b)^b = a.
Find the lone non-duplicate: XOR all elements. Pairs cancel (x^x = 0), zero is identity (0^x = x), so you're left with the unique element. XOR is commutative and associative — order doesn't matter.
Missing number in 0..n: XOR all elements with 0^1^2^…^n. Paired values cancel, leaving the missing one.
Bitmasks for subsets
Represent a subset of {0, 1, …, n−1} as an integer where bit i is 1 iff element i is in the subset. You get 2^n possible subsets for free, each as a single integer. This representation is the foundation of bitmask DP.
Check if element i is in mask: (mask >> i) & 1.
Add element i: mask | (1 << i).
Remove element i: mask & ~(1 << i).
Iterate all subsets of mask: for s = mask; s > 0; s = (s−1) & mask.
Counting set bits (popcount)
Hardware POPCNT: on any modern CPU, __builtin_popcount(n) (C/C++), Integer.bitCount(n) (Java), or bin(n).count('1') (Python) compile to a single POPCNT instruction. Always prefer this.
Brian Kernighan's method: while n: n &= n−1; count++. Clears one bit per iteration, so it runs in \(O(popcount(n)\)) — great when very few bits are set.