二項係数 binom(n, r) を,小さい素数 p に対して mod p で求める方法に関する記事です.
観察
p = 3 に関していくつか書いてみると次のようになっている.
0 1
1 1 1
2 1 2 1
10 1 0 0 1
11 1 1 0 1 1
12 1 2 1 1 2 1
20 1 0 0 2 0 0 1
21 1 1 0 2 2 0 1 1
22 1 2 1 2 1 2 1 2 1
100 1 0 0 0 0 0 0 0 0 1
101 1 1 0 0 0 0 0 0 0 1 1
102 1 2 1 0 0 0 0 0 0 1 2 1
110 1 0 0 1 0 0 0 0 0 1 0 0 1
111 1 1 0 1 1 0 0 0 0 1 1 0 1 1
112 1 2 1 1 2 1 0 0 0 1 2 1 1 2 1
120 1 0 0 2 0 0 1 0 0 1 0 0 2 0 0 1
こんな感じの構造になっている:
例: p = 3
例として $p = 3$ の場合には, 上の図から,以下のように計算できる.ただし,$q < 3^k$.
$$ \begin{eqnarray} % \binom00 &=& 1 \\ % \binom{3^k + q}{r} &=& \begin{cases} \displaystyle{\binom{q}{r}} & \text{if }\; 0 \leq r \leq q \\ \displaystyle{\binom{q}{r - 3^k}} & \text{if }\; 3^k \leq r \\ 0 & \text{if }\; q < r < 3^k \\ \end{cases} \\ % \binom{2\cdot 3^k + q}{r} &=& \begin{cases} \displaystyle{\binom{q}{r}} & \text{if }\; 0 \leq r \leq q \\ \displaystyle{2\binom{q}{r - 3^k}} & \text{if }\; 3^k \leq r \leq 2\cdot 3^k + q \\ \displaystyle{\binom{q}{r - 2\cdot 3^k}} & \text{if }\; 2\cdot 3^k \leq r \\ 0 & \text{if }\; q < r < 3^k,\; 3^k + q < r < 2\cdot 3^k \\ \end{cases} \\ % \end{eqnarray} $$
列 $s(n) := [\binom{n}{r} \mid 0 \leq r \leq n]$ が必要ならば,以下のように計算できる. $$ \begin{eqnarray} s(0) &=& [1] \\ s(3^k + q) &=& s(q) ⧺ z ⧺ s(q) \\ s(2\cdot 3^k + q) &=& s(q) ⧺ z ⧺ 2 \cdot s(q) ⧺ z ⧺ s(q) \end{eqnarray} $$ ただし,$z$ は,$0$ を $3^k - q - 1$ 個並べた列.
binom(n, r)
一般に,小さい素数$p$ に対しては,以下のようになる.
$n = c\cdot p^k + q$,$1 \leq c < p$,$q < p^k$,$r = d\cdot p^k + t$,$0 \leq d < p$,$t < p^k$ とすると,
$$ \begin{eqnarray} \binom{0}{0} &=& 1 \\ \binom{n}{r} = \binom{c\cdot p^k + q}{d\cdot p^k + t} &=& \begin{cases} \displaystyle{\binom{c}{d}\binom{q}{t}} & \text{if }\; 0 \leq t \leq q \\ 0 & \text{if }\; q < t \\ \end{cases} \\ \end{eqnarray} $$
$\binom{n}{r}$ の時間計算量は $O(\log n)$.
列 $s(n) := [\binom{n}{r} \mid 0 \leq r \leq n]$ が必要ならば,以下のように計算できる. 記号は上と同様. $$ \newcommand{\mybinom}[2]{\displaystyle{\binom{#1}{#2}}} \begin{eqnarray} s(0) &=& [1] \\ s(n) = s(c\cdot p^k + q) &=& \mybinom{c}{0}s(q) ⧺ z ⧺ \mybinom{c}{1}s(q) ⧺ z ⧺ \cdots ⧺ \mybinom{c}{c}s(q) \\ \end{eqnarray} $$ $z$は,$0$ を $p^k - q - 1$ 個並べた列. $s(n)$ の時間計算量は $O(n)$.
AtCoder
AtCoder ARC117 C - Tricolor Pyramid で,上の手順が使える.ただし,解説 の方法の方が思いつきやすいし,(列を求めるだけだから) 計算量は同じ.