π Math: Modular Inverse & Factorial Precomputation
- Topic: Combinatorics / Modular Arithmetic
- Tags: #algorithm #math #competitive-programming #template
- Complexity: precomputation, lookup
π‘ The Core Problem
When counting unique permutations (like ), we must perform division under a modulo ().
- Direct division is not allowed in modular arithmetic.
- We must multiply by the Modular Multiplicative Inverse instead ().
- Computing this inverse from scratch using Fermatβs Little Theorem () takes time, which becomes a bottleneck inside loops.
β‘ The Optimized Recipe (Python)
This template precomputes both factorials and their inverse factorials in linear time ( total).
MOD = 10**9 + 7
MAX_N = 100000 # Adjust based on constraints
fact = [1] * (MAX_N + 1)
invFact = [1] * (MAX_N + 1)
# 1. Forward pass: Compute standard factorials
for i in range(1, MAX_N + 1):
fact[i] = (fact[i - 1] * i) % MOD
# 2. Heavy Lift: Compute the absolute last inverse factorial using Fermat's Little Theorem
invFact[MAX_N] = pow(fact[MAX_N], MOD - 2, MOD)
# 3. Backward pass: Cascade down to fill the rest of the inverses
for i in range(MAX_N, 0, -1):
invFact[i - 1] = (invFact[i] * i) % MOD
π How the Backward Pass Magic Works
[!NOTE] Mathematical Intuition
Instead of callingpow()times, we exploit the factorial relationship backwards:
BecauseBy multiplying our current inverse by as we count down, we get the previous inverse instantly using simple multiplication.
π Cheat Sheet: Code Snippets
Use these exact expressions in your combinatorial loops after running the precomputation:
-
To get :
fact[n] -
To get :
invFact[n] -
To calculate combinations ():
nCr = fact[n] * invFact[r] % MOD * invFact[n - r] % MOD