Collisions are guaranteed
More keys than slots means some slot is shared — the pigeonhole principle. The design question is how collisions are handled, not whether they occur.
Hash functions map keys to a small range with mod, and linear congruential generators produce pseudorandom sequences the same way. Both work because of number theory, and both fail in ways number theory predicts.
Core ideas
Two applications where the choice of modulus decides whether the method works or fails badly.
More keys than slots means some slot is shared — the pigeonhole principle. The design question is how collisions are handled, not whether they occur.
k mod 2^r uses only the low bits of the key, so structured keys collide heavily. A prime modulus uses all of them.
An LCG is completely determined by its seed. It looks random by some statistical measures and is entirely predictable, which matters for security.
The material
Both constructions, the number theory behind them, and their failure modes.
A function h mapping a large key space into {0, 1, …, m−1}. The simplest is h(k) = k mod m.
Since the key space is larger than the range, collisions are unavoidable: by the pigeonhole principle of “The Pigeonhole Principle” in Sets, Relations, and Functions, some slot receives more than one key. A hash table is therefore designed around collisions — by chaining, or by probing for another slot.
If m = 2^r, then k mod m depends only on the low r bits of k. Keys sharing those bits — addresses aligned to a boundary, identifiers with a common suffix — all collide. A prime modulus has no such structure to exploit.
Hashing memory addresses with m = 16 when every address is a multiple of 16 sends every key to slot 0. With m = 17 the same keys spread across all seventeen slots.
The birthday problem of “Computing Probabilities” in Discrete Probability gives the collision rate: with m slots and n keys, collisions become likely once n is around √m. A table of a million slots sees its first collision after about a thousand insertions, which is why load factors are managed rather than collisions avoided.
x_{n+1} = (a·x_n + c) mod m, from a seed x₀. The parameters a (multiplier), c (increment) and m (modulus) determine the whole sequence.
The sequence must eventually repeat, since there are only m possible values — pigeonhole again. The period is how long it takes, and it is at most m.
An LCG has full period m for every seed if and only if: gcd(c, m) = 1; a − 1 is divisible by every prime dividing m; and a − 1 is divisible by 4 if m is.
a = 5, c = 3, m = 8, seed 0: 0, 3, 2, 5, 4, 7, 6, 1, 0, … — full period 8, and the conditions hold. Change a to 4 and the sequence is 0, 3, 7, 7, 7, …: it collapses almost immediately, because a − 1 = 3 is not divisible by 2.
Even a full-period LCG is not statistically good. Consecutive values fall on a small number of hyperplanes in higher dimensions — the Marsaglia effect — and the low bits of a power-of-two-modulus LCG have very short periods. RANDU, an LCG shipped by IBM in the 1960s, was so bad in three dimensions that results computed with it were later retracted.
An LCG is trivially predictable: observing a few outputs determines the parameters and hence every future value. That is fine for a simulation and fatal for a key or a session token. Cryptographic generators are built so that predicting the next output is as hard as a problem believed intractable — and "looks random" is not the same requirement as "cannot be predicted".
Interactive
Algorithms with their traces
Method
The modulus decides the behaviour.
It uses all the bits of the key. A power of two uses only the low ones, which is where structured keys collide.
Chaining or open addressing. By the birthday argument they begin around √m insertions.
They guarantee full period. Failing them can collapse the sequence to a handful of values.
Session tokens, keys and nonces need a cryptographic generator. The distinction is about predictability, not about statistics.
m = 16, seed 1, comparing a good and a bad multiplier.
This is why the theorem is worth having. The failure is not a degradation — it is total, and it would be easy to ship without noticing if the seed happened to look fine. The conditions are three divisibility checks.
For m = 100, find a multiplier and increment giving full period, and one that fails. The three conditions are quick to verify and the failure is dramatic.
Something to change about this lesson? Write it down, tick it off when it is handled, and export the list when you want to act on it. Kept in this browser only: nothing is sent anywhere, and nobody is notified.
No recommendations yet for this lesson.