
I took MA1301 at NTNU this semester and didn’t expect any of it to help with competitive programming. I was wrong. Number theory shows up constantly in contest problems, and once you start recognizing the patterns a whole class of problems becomes a lot easier.
Fast modular exponentiation
A lot of contest problems hand you huge numbers and ask for the result modulo \(10^9+7\). If you try to compute something like \(2^{1000000}\) the naive way, you’ll either overflow or time out. Fast modular exponentiation gets you there in \(O(\log n)\) time:
1 | def mod_pow(base, exponent, modulus): |
The trick is squaring the base on each iteration and using the bits of the exponent to decide when to fold it into the result.
Modular inverses with Fermat’s little theorem
Fermat’s little theorem says that for a prime \(p\) and any integer \(a\) not divisible by \(p\):
\[a^{p-1}\equiv 1\pmod{p}\]
Which means \(a^{p-2}\) is the modular inverse of \(a\) mod \(p\). Once you have that, dividing in modular arithmetic becomes multiplying by the inverse, which is much easier to reason about.
For non-prime moduli you fall back to the extended Euclidean algorithm:
1 | def mod_inverse(a, m): |
Chinese remainder theorem
Sometimes you get a system of modular equations that looks hopeless:
\[x \equiv a_1 \pmod{m_1}\] \[x \equiv a_2 \pmod{m_2}\] \[\vdots\] \[x \equiv a_n \pmod{m_n}\]
The Chinese remainder theorem says that if the moduli are pairwise coprime, there’s a unique solution modulo \(m_1 m_2 \cdots m_n\). The construction is careful bookkeeping more than anything else:
1 | def chinese_remainder(remainders, moduli): |
I’ve used this for problems that combine multiple modular constraints, especially the ones where the constraints come from different periodic processes that happen to align somewhere in the future.
Euler’s totient function
The totient function \(\phi(n)\) counts how many integers in \([1, n]\) are coprime to \(n\). The product formula is:
\[\phi(n) = n \prod_{p \mid n} \left(1 - \frac{1}{p}\right)\]
This generalizes Fermat’s little theorem to non-prime moduli (Euler’s theorem) and shows up any time you need to count coprime pairs or simplify exponents in modular arithmetic.
When you actually use this
The thing that surprised me is how often these techniques show up in problems that look like they have nothing to do with number theory. A counting problem with periodic structure usually wants either CRT or the totient function. A problem with exponents in the millions usually wants fast modular exponentiation. A problem about cancellation in modular arithmetic usually wants modular inverses.
I keep a small toolkit of these in my competitive programming repo so I can drop them in when something looks familiar.