Bit Representation & Sets as Bits¶
Integers as bit vectors pack many boolean flags into one machine word. In competitive programming, subset of \(\{0,\ldots,n-1\}\) is often uint32_t or uint64_t with bit i meaning “element \(i\) is included.”
Core operations¶
For a mask m and index i (0-based):
| Intent | Expression |
|---|---|
| Test if \(i\) in set | (m >> i) & 1 or (m >> i) & 1u |
| Set bit \(i\) | m \| (1u << i) |
| Clear bit \(i\) | m & ~(1u << i) |
| Flip bit \(i\) | m ^ (1u << i) |
| Lowest set bit | m & -m (two’s complement; signed pitfalls—prefer unsigned) |
| Remove lowest set bit | m & (m - 1) |
#include <cstdint>
bool hasBit(uint32_t m, int i) { return (m >> i) & 1u; }
uint32_t setBit(uint32_t m, int i) { return m | (1u << i); }
uint32_t clearBit(uint32_t m, int i) { return m & ~(1u << i); }
int popcount(uint32_t m) { return __builtin_popcount(m); } // GCC/Clang
int lowestBitIndex(uint32_t m) { return __builtin_ctz(m); } // undefined if m==0
Use unsigned types for shifts to avoid undefined behavior with negative or oversized shifts.
Iterating subsets¶
All non-empty submasks of m:
All k-element subsets of n bits: combine with combinatorial generation or use when \(n\) is small.
Signed vs unsigned¶
Right shift of signed negative values is implementation-defined for >> in older C++ for negatives; for bit tricks prefer uint32_t / uint64_t.
Related¶
- Bitmask Tricks — more patterns and puzzles
- Bitmask DP — DP over subset masks
- Boolean Counter / subsets — enumerating all
0 .. 2^n-1