Math Utilities
Number-theoretic helpers used throughout competitive programming: modular arithmetic, combinatorics, and the like.
Rust Implementation
Modular binomial coefficients (``nCr mod p``) and other number-theoretic helpers. View the rendered API reference →
1//! Precomputed modular binomial coefficients: `nCr mod p`.
2//!
3//! [`ModBinomial::new`] builds factorials and inverse factorials up to `max_n`
4//! in `O(max_n)` time using Fermat's little theorem for the modular inverse
5//! (`modulo` must be prime). Each subsequent [`ModBinomial::ncr`] call is `O(1)`.
6
7/// Binomial-coefficient table modulo a prime `modulo`.
8pub struct ModBinomial {
9 fact: Vec<i64>,
10 inv_fact: Vec<i64>,
11 modulo: i64,
12}
13
14impl ModBinomial {
15 /// Build the table for all `n` in `0..=max_n`. `modulo` must be prime
16 /// (the common choice is `1_000_000_007` or `998_244_353`).
17 pub fn new(max_n: usize, modulo: i64) -> Self {
18 let mut fact = vec![0; max_n + 1];
19 let mut inv_fact = vec![0; max_n + 1];
20
21 fact[0] = 1;
22 inv_fact[0] = 1;
23
24 for i in 1..=max_n {
25 fact[i] = (fact[i - 1] * i as i64) % modulo;
26 }
27
28 inv_fact[max_n] = Self::power(fact[max_n], modulo - 2, modulo);
29 for i in (1..=max_n).rev() {
30 inv_fact[i - 1] = (inv_fact[i] * i as i64) % modulo;
31 }
32
33 Self {
34 fact,
35 inv_fact,
36 modulo,
37 }
38 }
39
40 fn power(mut base: i64, mut exp: i64, modulo: i64) -> i64 {
41 let mut res = 1;
42 base %= modulo;
43 while exp > 0 {
44 if exp % 2 == 1 {
45 res = (res * base) % modulo;
46 }
47 base = (base * base) % modulo;
48 exp /= 2;
49 }
50 res
51 }
52
53 /// Compute `nCr mod modulo`. Returns `0` when `r > n`.
54 pub fn ncr(&self, n: usize, r: usize) -> i64 {
55 if r > n {
56 return 0;
57 }
58 let denom = (self.inv_fact[r] * self.inv_fact[n - r]) % self.modulo;
59 (self.fact[n] * denom) % self.modulo
60 }
61}