Peel the ones, then 2^k mod 37
· algorithms
lowbit walks every 1. A 37-slot table names the exponent, because 2^k is unique mod 37.
A nonnegative int . How many s does it have?
The brute loop always works. Smarter: take lowbit, that is the first , count it, then n -= lowbit and repeat until .
int population(int n) { int p = 0; while (n > 0) { n -= n & -n; ++p; } return p;}Side note: C++ already has std::popcount.
Now I want the positions. Same peel. The remaining job: given a lowbit , recover .
A fat table
Hash it. Build an array long enough that index stores . I used , which does not even cover every int, and every slot that is not a power of two is wasted.
std::array<int, (1 << 20) + 1> create_power_to_exponent_map_naive() { std::array<int, (1 << 20) + 1> power_to_exponent_map = {}; for (int k = 0; k <= 20; ++k) { power_to_exponent_map[1 << k] = k; } return power_to_exponent_map;}Compress with 37
The claim is that the residues are pairwise distinct modulo :
So a table of length can store at index . I only need for a 32-bit int, but the residues still live in , so the array stays size .
std::array<int, 37> create_power_to_exponent_map() { std::array<int, 37> power_to_exponent_map = {}; for (int k = 0; k <= 30; ++k) { power_to_exponent_map[static_cast<std::size_t>((1 << k) % 37)] = k; } return power_to_exponent_map;}
const auto kPowerToExponentMap = create_power_to_exponent_map();
std::vector<int> find_bit_positions(int n) { std::vector<int> positions; while (n > 0) { int lowbit = n & (-n); int position = kPowerToExponentMap[static_cast<size_t>(lowbit % 37)]; positions.push_back(position); n -= lowbit; } return positions;}Take n = 0b1110110. Peel: , , , , . Already , so the table is doing real compression — slot holds .
Why no collisions
If with , then since we may cancel and obtain . A collision is exactly when some positive exponent smaller than already yields . That is the language of multiplicative order.
Let be an integer and let satisfy . The multiplicative order of modulo is the smallest positive integer such that
It is denoted .
The coprimality hypothesis is not decoration: it guarantees that some power of is congruent to , so a least such positive exponent exists. Note that is trivial and does not count — zero is not a positive integer.
Since is prime and , Fermat’s little theorem applies.
Let be a prime number. Then for every integer ,
Equivalently, if (that is, if ), then
Taking and , the second form gives
So exists, and it is at most . Fermat does not say that is the least such exponent. If some already satisfied , the powers would collide. To pin the order down we need the following.
Let and let with . Then for every integer ,
Proof
Let .
() By definition, . Write for some integer . Then
() By the division algorithm there exist unique integers such that and . Then
Since , we have , and therefore
As , we also have . Hence , i.e.
But is the least positive integer with this property and , so . Thus .
Apply this with and . Fermat already gave , so . The positive divisors of are . It remains to check that none of the proper ones works:
None of these is . Therefore , and
No collisions.