卢卡斯定理 / Lucas \text{Lucas} Lucas定理
现有问题:
给定整数 n , m , p n,m,p n,m,p,求 ( n m ) m o d p \dbinom{n}{m}\bmod p (mn)modp,保证 p ∈ P p\in\mathbb{P} p∈P。
1 ≤ n , m , p ≤ 1 0 5 1\leq n,m,p \leq 10^5 1≤n,m,p≤105。
可以用 Lucas 定理解决。
定义
对于 p ∈ P p\in\mathbb{P} p∈P,有 ( n m ) m o d p = ( ⌊ n / p ⌋ ⌊ m / p ⌋ ) × ( n m o d p m m o d p ) m o d p \dbinom{n}{m}\bmod p = \dbinom{\lfloor n / p \rfloor}{\lfloor m / p \rfloor}\times\dbinom{n\bmod p}{m\bmod p}\bmod p (mn)modp=(⌊m/p⌋⌊n/p⌋)×(mmodpnmodp)modp
另一种形式: ( n m ) m o d p = ∏ i = 1 k ( a i b i ) m o d p \dbinom{n}{m}\bmod p = \displaystyle\prod\limits_{i=1}^k\dbinom{a_i}{b_i}\bmod p (mn)modp=i=1∏k(biai)modp( a , b a,b a,b 分别为 n , m n,m n,m 在 p p p 进制下的某一位, k k k 是它们 p p p 进制位数的较大值)。
证明
以下的 p ∈ P p\in\mathbb{P} p∈P。
∵ ( p n ) m o d p = p ! n ! ( p − n ) ! = [ n = 0 ∨ n = p ] \because\dbinom{p}{n}\bmod p = \displaystyle\frac{p!}{n!(p-n)!}=[n=0 \lor n=p] ∵(np)modp=n!(p−n)!p!=[n=0∨n=p]
∴ ( a + b ) p = ∑ n = 0 p ( p n ) a n b p − n ≡ ∑ n = 0 p [ n = 0 ∨ n = p ] a n b p − n ≡ a p + b p ( m o d p ) \begin{aligned}\therefore(a+b)^p&=\displaystyle\sum\limits_{n=0}^p\dbinom{p}{n}a^nb^{p-n}\\&\equiv\sum_{n=0}^p[n=0\lor n=p]a^nb^{p-n}\\&\equiv a^p+b^p(\bmod p)\end{aligned} ∴(a+b)p=n=0∑p(np)anbp−n≡n=0∑p[n=0∨n=p]anbp−n≡ap+bp(modp)
上面的结论可以用费马小定理推,但是这里没有用。所以这个推导也适用于多项式。
设 f p ( x ) = ( a x n + b x m ) m o d p f^p(x)=(ax^n+bx^m)\bmod p fp(x)=(axn+bxm)modp,则
( a x n + b x m ) p ≡ a p x p n + b p x p m ≡ a x p n + b x p m ≡ f ( x p ) ( m o d p ) \begin{aligned}(ax^n+bx^m)^p&\equiv a^px^{pn}+b^px^{pm}\\&\equiv ax^{pn}+bx^{pm}\\&\equiv f(x^p)(\bmod p)\end{aligned} (axn+bxm)p≡apxpn+bpxpm≡axpn+bxpm≡f(xp)(modp)
设 s = ⌊ n p ⌋ , t = ⌊ m p ⌋ , q = n m o d p , w = m m o d p s=\lfloor\displaystyle\frac{n}{p}\rfloor, t=\lfloor\displaystyle\frac{m}{p}\rfloor,q=n\bmod p, w=m\bmod p s=⌊pn⌋,t=⌊pm⌋,q=nmodp,w=mmodp,则有 n = s p + q , m = t p + w n=sp+q,m=tp+w n=sp+q,m=tp+w。
( 1 + x ) n ≡ ( ( 1 + x ) p ) s ( 1 + x ) q ≡ ( 1 + x p ) s + ( 1 + x ) q ≡ ∑ i = 1 s ( s i ) x p i × ∑ i = 1 q ( q j ) x j ( m o d p ) \begin{aligned}(1+x)^n&\equiv ((1+x)^p)^s(1+x)^q\\&\equiv (1+x^p)^s+(1+x)^q\\&\equiv\sum\limits_{i=1}^s\dbinom{s}{i}x^{pi}\times\sum\limits_{i=1}^q\dbinom{q}{j}x^{j} (\bmod p)\end{aligned} (1+x)n≡((1+x)p)s(1+x)q≡(1+xp)s+(1+x)q≡i=1∑s(is)xpi×i=1∑q(jq)xj(modp)
又 ( 1 + x ) n = ∑ i = 1 s p + q ( s p + q i ) x i (1+x)^n=\displaystyle\sum\limits_{i=1}^{sp+q}\dbinom{sp+q}{i}x^i (1+x)n=i=1∑sp+q(isp+q)xi
∴ ∑ i = 1 s p + q ( s p + q i ) x i ≡ ∑ i = 1 s ( s i ) x p i × ∑ i = 1 q ( q j ) x j ( m o d p ) \therefore\displaystyle\sum\limits_{i=1}^{sp+q}\dbinom{sp+q}{i}x^i\equiv\sum\limits_{i=1}^s\dbinom{s}{i}x^{pi}\times\sum\limits_{i=1}^q\dbinom{q}{j}x^{j} (\bmod p) ∴i=1∑sp+q(isp+q)xi≡i=1∑s(is)xpi×i=1∑q(jq)xj(modp)
可以发现,当 m ≤ n m\leq n m≤n 时,两边都有 x t p + m x^{tp+m} xtp+m 项。对比两边系数:
( s p + q t p + w ) x t p + w ≡ ( s t ) x t p × ( q w ) x w ( s p + q t p + w ) ≡ ( s t ) × ( q w ) ( n m ) ≡ ( ⌊ n p ⌋ ⌊ m p ⌋ ) ( n m o d p m m o d p ) ( m o d p ) \begin{aligned} \dbinom{sp+q}{tp+w}x^{tp+w}&\equiv \dbinom{s}{t}x^{tp}\times\dbinom{q}{w}x^w\\ \dbinom{sp+q}{tp+w}&\equiv\dbinom{s}{t}\times\dbinom{q}{w}\\ \dbinom{n}{m}&\equiv\dbinom{\lfloor\frac{n}{p}\rfloor}{\lfloor\frac{m}{p}\rfloor}\dbinom{n\bmod p}{m \bmod p}(\bmod p) \end{aligned} (tp+wsp+q)xtp+w(tp+wsp+q)(mn)≡(ts)xtp×(wq)xw≡(ts)×(wq)≡(⌊pm⌋⌊pn⌋)(mmodpnmodp)(modp)
得证。
const int N = 1e5 + 10;
long long A[N];//预处理出阶乘
long long qp(long long a, long long b, long long p);//快速幂
long long C(long long n, long long m, long long p){
if(m > n) return 0;
return (A[n] * qp(A[m], p-2, p) % p) *
qp(A[n-m], p-2, p) % p;
}
long long Lucas(long long n, long long m, long long p){
if(!m) return 1;
return C(n%p, m%p, p) * Lucas(n/p, m/p, p) % p;
}
long long solve(long long n, long long m, long long p){
A[0] = 1;
for(int i = 1; i <= n; ++ i) A[i] = A[i-1] * i % p;
return Lucas(n, m, p);
}
例题
Luogu P2480 [SDOI2010] 古代猪文(基础数论全家桶)
求 g ∑ d ∣ n C n d m o d 999911659 g^{\sum_{d|n} C_n^d}\bmod 999911659 g∑d∣nCndmod999911659。
1 ≤ n , g ≤ 1 0 9 1\leq n,g \leq 10^9 1≤n,g≤109。
- 因为 999911659 ∈ P 999911659\in \mathbb{P} 999911659∈P。
- 所以由欧拉定理可知, g 999911658 ≡ 1 ( m o d 999911659 ) g^{999911658}\equiv 1(\bmod 999911659) g999911658≡1(mod999911659),注意这里要有个特判:当 g = 999911659 g=999911659 g=999911659 时直接输出 0 0 0 结束程序。
- 所以原式 = g ∑ d ∣ n C n d m o d 999911658 m o d 999911659 =g^{\sum_{d|n} C_n^d\bmod999911658}\bmod 999911659 =g∑d∣nCndmod999911658mod999911659。
- 999911658 = 2 ∗ 3 ∗ 4679 ∗ 35617 999911658=2*3*4679*35617 999911658=2∗3∗4679∗35617。
- 令 t = ∑ d ∣ n C n d m o d 999911658 t=\sum_{d|n} C_n^d\bmod999911658 t=∑d∣nCndmod999911658。
- 则 { t ≡ ∑ d ∣ n C n d ( m o d 2 ) t ≡ ∑ d ∣ n C n d ( m o d 3 ) t ≡ ∑ d ∣ n C n d ( m o d 4679 ) t ≡ ∑ d ∣ n C n d ( m o d 35617 ) \begin{cases}t\equiv\sum_{d|n} C_n^d(\bmod2)\\t\equiv\sum_{d|n} C_n^d(\bmod3)\\t\equiv\sum_{d|n} C_n^d(\bmod4679)\\t\equiv\sum_{d|n} C_n^d(\bmod35617)\end{cases} ⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧t≡∑d∣nCnd(mod2)t≡∑d∣nCnd(mod3)t≡∑d∣nCnd(mod4679)t≡∑d∣nCnd(mod35617)。
- 每一项用 Lucas,然后用 CRT 求 t t t。
typedef long long ll;
const int N = 35620, P = 999911658;
ll A[N], x[4], y[4] = {2, 3, 4679, 35617};
ll qp(ll a, ll b, ll p);
ll C(ll n, ll m, ll p);
ll Lucas(ll n, ll m, ll p);
ll CRT(){
ll ans = 0;
for(int k = 0; k <= 3; ++ k)
ans = (ans + x[k] * (P/y[k]) % P * qp(P/y[k], y[k]-2, y[k])) % P;
return ans;
}
ll solve(ll n, ll g){
if(g == P + 1) return 0;
for(int k = 0; k <= 3; ++ k){
A[0] = 1;
for(ll i = 1; i <= y[k]; ++ i) A[i] = A[i-1] * i % y[k];
for(ll i = 1; i * i <= n; ++ i) if(n%i == 0){
x[k] = (x[k] + Lucas(n, i, y[k])) % y[k];
if(i * i != n) x[k] = (x[k] + Lucas(n, n/i, y[k])) % y[k];
}
}
return qp(g, CRT(), P+1);
}
扩展卢卡斯定理 / exLucas \text{exLucas} exLucas
问题如下:
给定整数 n , m , p n,m,p n,m,p,求 ( n m ) m o d p \dbinom{n}{m}\bmod p (mn)modp,不保证 p ∈ P p\in\mathbb{P} p∈P。
1 ≤ n , m ≤ 1 0 18 , 2 ≤ p ≤ 1 0 6 1\leq n,m \leq 10^{18}, 2\leq p \leq 10^6 1≤n,m≤1018,2≤p≤106。
其实和 Lucas 没什么关系。以下是解决步骤:
解法
Step 1. 分解 p p p
对于 p p p 进行质因数分解: p = ∏ i = 1 r p i k i p=\prod\limits_{i=1}^r p_i^{k_i} p=i=1∏rpiki。将原式化成若干同余方程:
{ ( n m ) ≡ a 1 ( m o d p 1 k 1 ) ( n m ) ≡ a 2 ( m o d p 2 k 2 ) . . . ( n m ) ≡ a i ( m o d p i k i ) \begin{cases}\dbinom{n}{m}\equiv a_1(\bmod p_1^{k_1})\\\dbinom{n}{m}\equiv a_2(\bmod p_2^{k_2})\\...\\\dbinom{n}{m}\equiv a_i(\bmod p_i^{k_i})\end{cases} ⎩⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎧(mn)≡a1(modp1k1)(mn)≡a2(modp2k2)...(mn)≡ai(modpiki)
因为 p i k i p_i^{k_i} piki 两两互素,最后使用 CRT 求解即可。
Step 2. 求解 a i a_i ai
a i = ( n m ) m o d p i k i = n ! m ! ( n − m ) ! m o d p i k i a_i=\dbinom{n}{m}\bmod p_i^{k_i}=\displaystyle\frac{n!}{m!(n-m)!}\bmod p_i^{k_i} ai=(mn)modpiki=m!(n−m)!n!modpiki,但是 p i k i p_i^{k_i} piki 仍然不是质数,不能求出分母的逆元。所以将分子分母的所有 p i p_i pi 提出来:
a i = n ! p i k 1 m ! p i k 2 × ( n − m ) ! p i k 3 × p i k 1 − k 2 − k 3 a_i=\displaystyle\frac{\frac{n!}{p_i^{k_1}}}{\frac{m!}{p_i^{k_2}}\times\frac{(n-m)!}{p_i^{k_3}}}\times p_i^{k1-k2-k3} ai=pik2m!×pik3(n−m)!pik1n!×pik1−k2−k3,分母可以求逆元。
Step 3.求解 n ! p k \displaystyle\frac{n!}{p^k} pkn!
举个例子: n = 22 , p = 3 , k = 2 n=22,p=3,k=2 n=22,p=3,k=2。
n ! = 1 ∗ 2 ∗ . . . ∗ 22 = 3 7 ∗ ( 1 ∗ 2 ∗ 3 ∗ 4 ∗ 5 ∗ 6 ∗ 7 ) ∗ ( 1 ∗ 2 ∗ 4 ∗ 5 ∗ 7 ∗ 8 ) ∗ ( 10 ∗ 11 ∗ 13 ∗ 14 ∗ 16 ∗ 17 ) ∗ ( 19 ∗ 20 ∗ 22 ) ≡ 3 7 ∗ 7 ! ∗ ( 1 ∗ 2 ∗ 4 ∗ 5 ∗ 7 ∗ 8 ) 2 ∗ ( 1 ∗ 2 ∗ 4 ) ( m o d p k ) \begin{aligned}n!&=1*2*...*22\\&=3^7*(1*2*3*4*5*6*7)*(1*2*4*5*7*8)*(10*11*13*14*16*17)*(19*20*22)\\&\equiv3^7*7!*(1*2*4*5*7*8)^2*(1*2*4)(\bmod p^k)\end{aligned} n!=1∗2∗...∗22=37∗(1∗2∗3∗4∗5∗6∗7)∗(1∗2∗4∗5∗7∗8)∗(10∗11∗13∗14∗16∗17)∗(19∗20∗22)≡37∗7!∗(1∗2∗4∗5∗7∗8)2∗(1∗2∗4)(modpk)
分为三个部分
- 3 7 3^7 37 为 p n p p^{\frac{n}{p}} ppn(会被分母消掉,不用算)。
- 7 ! 7! 7! 递归求解
- 在 m o d p k \mod p^k modpk 意义下是循环节,有 n p k \frac{n}{p^k} pkn 个,剩下的那部分暴力求解。
ll calc(ll n, ll p, ll pk){
if(!n) return 1;
ll ans = 1;
for(ll i = 1; i <= pk; ++ i)//每个循环节
if(i % p) ans = ans * i % pk;
ans = qp(ans, n/pk, pk);//所有循环节
for(ll i = 1; i <= n % pk; ++ i)//剩下的
if(i % p) ans = ans * i % pk;
return ans * calc(n/p, p, pk) % pk;//递归求解
}
完整代码
typedef long long ll;
const int N = 1e6 + 10;
ll a[N], b[N]; int tot;
ll qp(ll a, ll b, ll p);
void exgcd(ll &x, ll &y, ll a, ll b);
ll inv(ll x, ll p);
ll calc(ll n, ll p, ll pk){
if(!n) return 1; ll ans = 1;
for(ll i = 1; i <= pk; ++ i) if(i%p) ans = ans * i % pk;
ans = qp(ans, n/pk, pk);
for(ll i = 1; i <= n%pk; ++i) if(i%p) ans = ans * i % pk;
return ans * calc(n/p, p, pk) % pk;
}
ll C(ll n, ll m, ll p, ll pk){
if(!n || !m || n==m) return 1; if(n < m) return 0;
ll nn = calc(n, p, pk), mm = calc(m, p, pk), nm = calc(n-m, p, pk);
ll cnt = 0, k = n - m;//cnt即上文k1-k2-k3
while(n) n /= p, cnt += n;
while(m) m /= p, cnt -= m;
while(k) k /= p, cnt -= k;
return nn * inv(mm, pk) % pk * inv(nm, pk) % pk *
qp(p, cnt, pk) % pk;
}
ll CRT(){
ll M = 1, ans = 0;
for(int i = 1; i <= tot; ++ i) M *= b[i];
for(int i = 1; i <= tot; ++ i)
ans += a[i] * (M/b[i]) * inv(M/b[i], b[i]);
return (ans % M + M) % M;
}
ll exLucas(ll n, ll m, ll p){
for(ll i = 2; i * i <= p && p >= 1; ++ i){
ll pk = 1;
while(p%i == 0) p /= i, pk *= i;
if(pk > 1) a[++tot] = C(n, m, i, pk), b[tot] = pk;
}
if(p > 1) a[++tot] = C(n, m, p, p), b[tot] = p;
return CRT();
}