注意:Lucas 定理和扩展 Lucas 算法没有关系。取名“扩展 Lucas”仅仅是因为该算法能解决 Lucas 定理所解决的问题的推广情况。
Lucas(卢卡斯定理)是一个用于加快计算小质数模意义下的组合数的定理。
具体地,它能解决形如
( n m ) m o d p \binom{n}{m} \bmod p (mn)modp
的问题,其中 p p p 为质数。
公式为:
( n m ) ≡ ( ⌊ n p ⌋ ⌊ m p ⌋ ) ( n m o d p m m o d p ) ( m o d p ) \binom{n}{m} \equiv \binom{\lfloor\frac{n}{p}\rfloor}{\lfloor\frac{m}{p}\rfloor} \binom{n \bmod p}{m \bmod p} \pmod p (mn)≡(⌊pm⌋⌊pn⌋)(mmodpnmodp)(modp)
首先证明一个式子
( 1 + x ) p ≡ 1 + x p ( m o d p ) (1+x)^p \equiv 1+x^p \pmod p (1+x)p≡1+xp(modp)
直接把左边二项式展开,得到
1 + ( p 1 ) x + ( p 2 ) x 2 + ⋯ + ( p p ) x p 1+\binom{p}{1}x+\binom{p}{2}x^2+\cdots+\binom{p}{p}x^p 1+(1p)x+(2p)x2+⋯+(pp)xp
注意到 p p p 是质数,所以无法在组合数分母上被约去,因此第二项到第 p p p 项都是 p p p 的倍数。因此上式成立。
令 n = k 1 p + c 1 n=k_1p+c_1 n=k1p+c1, m = k 2 p + c 2 m=k_2p+c_2 m=k2p+c2。
考虑 ( 1 + x ) n (1+x)^n (1+x)n。其在模 p p p 意义下有如下等式:
( 1 + x ) n = ( 1 + x ) k 1 p + c 1 = ( 1 + x ) k 1 p ( 1 + x ) c 1 = ( 1 + x p ) k 1 ( 1 + x ) c 1 \begin{aligned} & (1+x)^n \\ = & (1+x)^{k_1p+c_1} \\ = & (1+x)^{k_1p} (1+x)^{c_1} \\ = & (1+x^p)^{k_1}(1+x)^{c_1} \\ \end{aligned} ===(1+x)n(1+x)k1p+c1(1+x)k1p(1+x)c1(1+xp)k1(1+x)c1
展开这个式子,考察 x m x^m xm 项。
在 ( 1 + x ) n (1+x)^n (1+x)n 中其系数为 ( n m ) \binom{n}{m} (mn)。在 ( 1 + x p ) k 1 ( 1 + x ) c 1 (1+x^p)^{k_1}(1+x)^{c_1} (1+xp)k1(1+x)c1 中,次数分解为 k 2 p + c 2 k_2p+c_2 k2p+c2。
分别从两个二项式中提取次数,可得系数为
( k 1 k 2 ) ( c 1 c 2 ) \binom{k_1}{k_2}\binom{c_1}{c_2} (k2k1)(c2c1)
于是
( n m ) ≡ ( k 1 k 2 ) ( c 1 c 2 ) ( m o d p ) \binom{n}{m} \equiv \binom{k_1}{k_2}\binom{c_1}{c_2} \pmod p (mn)≡(k2k1)(c2c1)(modp)
ExLucas(Extended Lucas,扩展卢卡斯)是一个用于加快计算小模数下的模意义组合数的算法。
具体地,它能解决形如
( n m ) m o d p \binom{n}{m} \bmod p (mn)modp
的问题,其中 p p p 不一定是质数。
算法的核心是利用质因数分解与中国剩余定理,将问题转化为质数幂次模意义下的计算,然后利用式子进行问题规模的缩小并递归求解。
令模数为 p p p,其质因数分解 p = p 1 α 1 p 2 α 2 ⋯ p=p_1^{\alpha_1}p_2^{\alpha_2}\cdots p=p1α1p2α2⋯
我们求解如下几个方程
{ ( n m ) ≡ a 1 ( m o d p 1 α 1 ) ( n m ) ≡ a 2 ( m o d p 2 α 2 ) ⋯ \left\{ \begin{aligned} &\binom{n}{m} \equiv a_1 \pmod {p_1^{\alpha_1}} \\ &\binom{n}{m} \equiv a_2 \pmod {p_2^{\alpha_2}} \\ &\cdots \end{aligned} \right. ⎩⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎧(mn)≡a1(modp1α1)(mn)≡a2(modp2α2)⋯
得出所有 a i a_i ai 后,用 CRT 合并即可求出答案。以下我们只考虑解决
( n m ) m o d P k \binom{n}{m} \bmod P^k (mn)modPk
其中 P P P 为质数。
考虑正常计算组合数的方法:
( n m ) = n ! m ! ( n − m ) ! \binom{n}{m} = \frac{n!}{m!(n-m)!} (mn)=m!(n−m)!n!
无法在此处使用该方法,因为逆元可能不存在。
一个数在模意义下存在逆元的充要条件是其与模数互质。因此我们考虑把每个数的模数因子都提出去计算,这样就会互质,就可以求逆元了。
于是令 f ( x ) f(x) f(x) 为 x ! x! x! 的 P P P 因子个数,有
( n m ) ≡ n ! P f ( n ) m ! P f ( m ) ( n − m ) ! P f ( n − m ) P f ( n ) − f ( m ) − f ( n − m ) ( m o d P k ) \binom{n}{m} \equiv \frac{\frac{n!}{P^{f(n)}}}{\frac{m!}{P^{f(m)}}\frac{(n-m)!}{P^{f(n-m)}}} P^{f(n)-f(m)-f(n-m)} \pmod {P^k} (mn)≡Pf(m)m!Pf(n−m)(n−m)!Pf(n)n!Pf(n)−f(m)−f(n−m)(modPk)
于是问题转化为求
x ! P f ( x ) m o d P k \frac{x!}{P^{f(x)}} \bmod P^k Pf(x)x!modPk
将 x x x 及以下所有 P P P 的倍数提出在外:
x ! = ( P × 2 P × ⋯ ) ( 1 × 2 × ⋯ ) x! = (P\times 2P\times \cdots)(1 \times 2 \times \cdots) x!=(P×2P×⋯)(1×2×⋯)
提出 P P P:
x ! = P ⌊ x P ⌋ ( ⌊ x P ⌋ ) ! ( 1 × 2 × ⋯ ) x!=P^{\lfloor\frac{x}{P}\rfloor} (\lfloor\frac{x}{P}\rfloor)! (1\times 2 \times \cdots) x!=P⌊Px⌋(⌊Px⌋)!(1×2×⋯)
后面的 ( 1 × 2 × ⋯ ) (1 \times 2 \times \cdots) (1×2×⋯),其在模 P k P^k Pk 意义下显然有周期。
具体地,该式实际形式为
( 1 × 2 × ⋯ × ( P k − 1 ) × ( P k + 1 ) × ( P k + 2 ) × ⋯ ) (1\times 2\times \cdots \times (P^k-1) \times (P^k+1) \times (P^k+2) \times \cdots) (1×2×⋯×(Pk−1)×(Pk+1)×(Pk+2)×⋯)
而在模 P k P^k Pk 意义下,其等同于
( 1 × 2 × ⋯ × ( P k − 1 ) × 1 × 2 × ⋯ ) (1\times 2\times \cdots \times (P^k-1) \times 1 \times 2 \times \cdots) (1×2×⋯×(Pk−1)×1×2×⋯)
我们把该式写成公式化表达
x ! ≡ P ⌊ x P ⌋ ( ⌊ x P ⌋ ) ! ( ∏ i = 1 , P ∤ i P k i ) ⌊ x P k ⌋ ( ∏ i = 1 , P ∤ i x m o d P k i ) ( m o d P k ) x! \equiv P^{\lfloor\frac{x}{P}\rfloor} (\lfloor\frac{x}{P}\rfloor)! (\prod_{i=1,P\nmid i}^{P^k} i)^{\lfloor\frac{x}{P^k}\rfloor}(\prod_{i=1,P\nmid i}^{x \bmod P^k} i) \pmod {P^k} x!≡P⌊Px⌋(⌊Px⌋)!(i=1,P∤i∏Pki)⌊Pkx⌋(i=1,P∤i∏xmodPki)(modPk)
最后那两个部分都是可以暴力的,而 ( ⌊ x P ⌋ ) ! (\lfloor\frac{x}{P}\rfloor)! (⌊Px⌋)! 可以递归求解。
然后考察 f ( x ) f(x) f(x) 怎么求。注意到一个方法是先筛选所有至少有一个 P P P 因子的数,然后筛选所有至少有两个 P P P 因子的数,依此类推。这个过程就是不断找一个数以内 P P P 的倍数的过程,公式化为下式: f(x)=0 (x<P)
f ( x ) = f ( ⌊ x P ⌋ ) + ⌊ x P ⌋ f(x) = f(\lfloor\frac{x}{P}\rfloor)+\lfloor\frac{x}{P}\rfloor f(x)=f(⌊Px⌋)+⌊Px⌋
边界为 f ( x ) = 0 ( x < P ) f(x)=0 \ (x
通过这个式子,我们也可以直接写出 g ( x ) = x ! P f ( x ) g(x)=\frac{x!}{P^{f(x)}} g(x)=Pf(x)x! 的递归表达式:
g ( x ) ≡ g ( ⌊ x P ⌋ ) ( ∏ i = 1 , P ∤ i P k i ) ⌊ x P k ⌋ ( ∏ i = 1 , P ∤ i x m o d P k i ) ( m o d P k ) g(x) \equiv g(\lfloor\frac{x}{P}\rfloor) (\prod_{i=1,P\nmid i}^{P^k} i)^{\lfloor\frac{x}{P^k}\rfloor}(\prod_{i=1,P\nmid i}^{x \bmod P^k} i) \pmod {P^k} g(x)≡g(⌊Px⌋)(i=1,P∤i∏Pki)⌊Pkx⌋(i=1,P∤i∏xmodPki)(modPk)
最后就是 P f ( n ) − f ( m ) − f ( n − m ) P^{f(n)-f(m)-f(n-m)} Pf(n)−f(m)−f(n−m) 的求解了。注意到 f f f 的递归式,直接求解就是 O ( log P n ) O(\log_P n) O(logPn) 的。
总结:
第一步复杂度 O ( p ) O(\sqrt p) O(p)。如果预线性筛出最小质因子可以做到 O ( log p ) O(\log p) O(logp),不过瓶颈不在这,没必要。
第二步总复杂度 O ( ∑ P log P n P k ) O(\sum_P \log_P n P^k) O(∑PlogPnPk),上界是 O ( p log n ) O(p\log n) O(plogn)。
第三步总复杂度 O ( ∑ P ( log P n + log n ) ) O(\sum_P (\log_P n + \log n)) O(∑P(logPn+logn)),上界是 O ( log p log n ) O(\log p\log n) O(logplogn)。
最后一步复杂度 O ( log 2 p ) O(\log^2 p) O(log2p)。