网站开发网页设计免费网站外链推广
0. 介绍
lucas定理用来求组合数取模的,在这里记录一下。
假设 p p p是一个质数,现在要求组合数 ( n m ) {n \choose m} (mn)模 p p p。
根据带余数除法可得
n = s p + q , 0 ≤ q < p m = t p + r , 0 ≤ r < p n=sp+q, \quad 0\le q <p\\ m=tp+r,\quad 0\le r <p\\ n=sp+q,0≤q<pm=tp+r,0≤r<p
那么有
( n m ) = ( s t ) ( q r ) ( m o d p ) {n\choose m}={s \choose t }{q \choose r}\quad (\bmod \ p) (mn)=(ts)(rq)(mod p)
1. 证明
不难得到
( 1 + x ) n = ( 1 + x ) s p + q = ( 1 + x ) s p ( 1 + x ) q = [ ( 1 + x ) p ] s ( 1 + x ) q \begin{align*} (1+x)^{n}&=(1+x)^{sp+q}\\ &=(1+x)^{sp}(1+x)^{q}\\ &=[(1+x)^{p}]^{s}(1+x)^q \end{align*} (1+x)n=(1+x)sp+q=(1+x)sp(1+x)q=[(1+x)p]s(1+x)q
引入结论
( p i ) m o d p = 0 , 1 ≤ i < p {p \choose i} \bmod p = 0, \quad 1 \le i < p (ip)modp=0,1≤i<p
根据二项式定理
( 1 + x ) p = 1 + x p + ∑ i = 1 p − 1 ( p i ) x i (1+x)^{p}=1+x^{p}+\sum_{i=1}^{p-1}{p \choose i}x^i (1+x)p=1+xp+i=1∑p−1(ip)xi
综合上面两式可以得到
( 1 + x ) p ≡ 1 + x p ( m o d p ) (1+x)^p \equiv1+x^p \quad (\bmod\ p) (1+x)p≡1+xp(mod p)
进而
[ ( 1 + x ) p ] s ≡ ( 1 + x p ) s ≡ ∑ i = 0 s ( s i ) x i p [(1+x)^p]^s \equiv (1+x^{p})^s \equiv \sum_{i=0}^{s}{s \choose i}x^{ip} [(1+x)p]s≡(1+xp)s≡i=0∑s(is)xip
同理可得
( 1 + x ) q ≡ ∑ j = 0 q ( q j ) x j (1+x)^q \equiv \sum_{j=0}^{q}{q \choose j}x^{j} (1+x)q≡j=0∑q(jq)xj
又由二项式定理可得,在 ( 1 + x ) n 中 (1+x)^n中 (1+x)n中 x m x^{m} xm的系数为
( n m ) = ( s p + q t p + r ) {n \choose m}={sp+q \choose tp+r} (mn)=(tp+rsp+q)
整理上面各式后可以得到
( n m ) ≡ ( s p + q t p + r ) ≡ ∑ i = 0 s ( s i ) x i p ∑ j = 0 q ( q j ) x j ( m o d p ) {n \choose m} \equiv {sp+q \choose tp+r} \\\equiv \sum_{i=0}^{s} {s \choose i} x^{ip} \sum_{j=0}^{q}{q \choose j}x_j\quad ( \bmod\ p) (mn)≡(tp+rsp+q)≡i=0∑s(is)xipj=0∑q(jq)xj(mod p)
观察可得,右边的式子只有当 i = t j = r i=t\ j=r i=t j=r时才能取到 x m x^{m} xm项。
因此
( n m ) ≡ ( s t ) ( q r ) ( m o d p ) {n \choose m} \equiv {s \choose t}{q \choose r} \quad (\ \bmod\ p) (mn)≡(ts)(rq)( mod p)
2. 代码
以Luogu p3807为例
#include <iostream>using ll = long long;static constexpr int MAXN = 100010;ll bc[MAXN+1];ll qpow(ll x, ll y, ll p) {ll tmp = x % p;ll ans = 1;while(y) {if (y & 1) ans = ans * tmp % p;tmp = tmp * tmp % p;y >>= 1;}return ans;
}
ll C(ll n, ll m, ll p) {if (n < m) return 0;return (bc[n] * qpow(bc[m], p - 2, p ) % p * qpow(bc[n - m], p - 2, p) % p);
}
ll Lucas(ll n, ll m, ll p) { if (!m) return 1;return Lucas( n / p, m / p, p) * C(n % p, m % p, p) % p;
}
int main( int argc, char *argv[])
{ ll n;ll m;ll p;int t;std::cin >> t;while (t--) {std::cin >> n >> m >> p;bc[0] = 1;for (int i = 1; i <= p;i++) {bc[i] = bc[i - 1] * i % p;}ll ans = Lucas(n + m, m, p);std::cout << ans << std::endl;}return 0;
}
3. 参考
百度-Lucas定理