【luogu P3807】【模板】卢卡斯定理/Lucas 定理(含 Lucas 定理证明)

【模板】卢卡斯定理/Lucas 定理

题目链接:luogu P3807

题目大意

求 C(n,n+m)%p 的值。
p 保证是质数。

思路

Lucas 定理内容

对于非负整数 n n n, m m m,质数 p p p,有:
C m n ≡ ∏ i = 0 k C m i n i (   m o d     p ) C_m^n\equiv \prod\limits_{i=0}^kC_{m_i}^{n^i}(\bmod\ p) Cmni=0kCmini(mod p)
其中 m = m k p k + . . . + m 1 p + m 0 m=m_kp^k+...+m_1p+m_0 m=mkpk+...+m1p+m0 n = n k p k + . . . + n 1 p + n 0 n=n_kp^k+...+n_1p+n_0 n=nkpk+...+n1p+n0。(其实就是 n , m n,m n,m p p p 进制展开)

那我们一般做题用的是递推式,也就是 C m n ≡ C ⌊ m / p ⌋ ⌊ n / p ⌋ C m   m o d   p n   m o d   p (   m o d     p ) C_m^n\equiv C_{\left\lfloor m/p\right\rfloor}^{\left\lfloor n/p\right\rfloor}C_{m\bmod p}^{n\bmod p}(\bmod\ p) CmnCm/pn/pCmmodpnmodp(mod p)
(当 n > m n>m n>m 时,我们规定 C m n = 0 C_{m}^n=0 Cmn=0

啥时候会用

我们有时候要算组合数,可能 C m n C_{m}^n Cmn n , m n,m n,m 很大,这时候一般做题就会让他取模一个数   m o d     p \bmod \ p mod p

那如果 p > m p>m p>m,我们可以愉快的用这个式子求: C m n = m ! n ! ( m − n ) ! C_{m}^n=\dfrac{m!}{n!(m-n)!} Cmn=n!(mn)!m!
算出 n ! n! n! ( m − n ) ! (m-n)! (mn)! 的逆元,就可以搞。

可当 m ⩾ p m\geqslant p mp 的时候,分母的乘法逆元可能不存在。(因为 x x x p p p 的倍数的话 x x x 就没有模 p p p 的逆元)

那这个时候我们就可以用 Lucas 定理把这个组合数拆成几个 m < p m<p m<p 的,就可以搞了。

证明

证明 Lucas 定理之前,我们先证明两个式子。


式一:

C p i ≡ p i C p − 1 i − 1 ≡ 0 (   m o d     p ) , ( 1 ⩽ i < p ) C_p^i\equiv \frac{p}{i}C_{p-1}^{i-1}\equiv0(\bmod\ p),(1\leqslant i<p) CpiipCp1i10(mod p),(1i<p)
证明:
C p i = p ! i ! ( p − i ) ! = p i ( p − 1 ) ! ( i − 1 ) ! ( p − 1 − ( i − 1 ) ) ! = p i C p − 1 i − 1 C_p^i=\dfrac{p!}{i!(p-i)!}=\dfrac{p}{i}\dfrac{(p-1)!}{(i-1)!(p-1-(i-1))!}=\frac{p}{i}C_{p-1}^{i-1} Cpi=i!(pi)!p!=ip(i1)!(p1(i1))!(p1)!=ipCp1i1
由于 1 ⩽ i < p 1\leqslant i<p 1i<p,故 i i i 会有 p p p 的逆元 i n v i inv_i invi
p i C p − 1 i − 1 = p × i n v i × C p − 1 i − 1 \frac{p}{i}C_{p-1}^{i-1}=p\times inv_i\times C_{p-1}^{i-1} ipCp1i1=p×invi×Cp1i1
那这个地方都是 p p p 的倍数,那它被 p p p 取模一定是 0 0 0,故得证。


式二:

根据二项式定理:
( 1 + n ) p ≡ C p 0 + C p 1 x + . . . + C p p − 1 x p − 1 + C p p x p (   m o d     p ) (1+n)^p\equiv C_p^0+C_p^1x+...+C_p^{p-1}x^{p-1}+C_p^px^p(\bmod\ p) (1+n)pCp0+Cp1x+...+Cpp1xp1+Cppxp(mod p)
再根据式一 C p i ≡ 0 (   m o d     p ) , ( 1 ⩽ i < p ) C_p^i\equiv0(\bmod\ p),(1\leqslant i<p) Cpi0(mod p),(1i<p),可以得到
( 1 + n ) p ≡ C p 0 + C p p x p ≡ 1 + x p (   m o d     p ) (1+n)^p\equiv C_p^0+C_p^px^p\equiv 1+x^p(\bmod\ p) (1+n)pCp0+Cppxp1+xp(mod p)


接着我们开始证明,先设 ⌊ m / p ⌋ = q m , ⌊ n / p ⌋ = q n , m   m o d   p = r m , n   m o d   p = r n \left\lfloor m/p\right\rfloor=q_m,\left\lfloor n/p\right\rfloor=q_n,m\bmod p=r_m,n\bmod p=r_n m/p=qm,n/p=qn,mmodp=rm,nmodp=rn
那有 m = q m p + r m , n = q n p + r n m=q_mp+r_m,n=q_np+r_n m=qmp+rm,n=qnp+rn

接着我们继续用二项式定理:
( 1 + x ) m = ∑ i = 1 m C m i x i (1+x)^m=\sum\limits_{i=1}^{m}C_{m}^ix^i (1+x)m=i=1mCmixi
然后我们把左边给化简:
( 1 + x ) m = ( 1 + x ) q m p + r m = ( 1 + x ) q m p ⋅ ( 1 + x ) r m = [ ( 1 + x ) p ] q m ⋅ ( 1 + x ) r m ≡ ( 1 + x p ) q m ⋅ ( 1 + x ) r m [ 式 二 ] ≡ ∑ i = 1 q m C q m i x i p ∑ i = 1 r m C r m i x i (   m o d     p ) \begin{aligned}(1+x)^m & =(1+x)^{q_mp+r_m} \\ & =(1+x)^{q_mp}\cdot(1+x)^{r_m} \\& =[(1+x)^p]^{q_m}\cdot(1+x)^{r_m}\\&\equiv(1+x^p)^{q_m}\cdot(1+x)^{r_m}[式二]\\&\equiv\sum\limits_{i=1}^{q_m}C_{q_m}^ix^{ip}\sum\limits_{i=1}^{r_m}C_{r_m}^{i}x^i(\bmod\ p)\end{aligned} (1+x)m=(1+x)qmp+rm=(1+x)qmp(1+x)rm=[(1+x)p]qm(1+x)rm(1+xp)qm(1+x)rm[]i=1qmCqmixipi=1rmCrmixi(mod p)

那就有:
∑ i = 1 m C m i x i ≡ ∑ i = 1 q m C q m i x i p ∑ i = 1 r m C r m i x i (   m o d     p ) \sum\limits_{i=1}^{m}C_{m}^ix^i\equiv\sum\limits_{i=1}^{q_m}C_{q_m}^ix^{ip}\sum\limits_{i=1}^{r_m}C_{r_m}^{i}x^i(\bmod\ p) i=1mCmixii=1qmCqmixipi=1rmCrmixi(mod p)

那对于任意一个数 z z z,必然会有一组 i , j i,j i,j 满足 x z = x p i x j x^z=x^{pi}x^j xz=xpixj
不难看出这其实就是满足 z = p i + j z=pi+j z=pi+j,所以当且仅当 i = ⌊ z p ⌋ , j = z   m o d   p i=\left\lfloor \dfrac{z}{p}\right\rfloor,j=z\bmod p i=pzj=zmodp
那也就是说左边的 i i i 取任意一个,右边都有一个新的跟它对于恒等。
左边 i = x i=x i=x,右边的就分别是 i = ⌊ x p ⌋ , i = x   m o d   p i=\left\lfloor \dfrac{x}{p}\right\rfloor,i=x\bmod p i=px,i=xmodp

那当 i = x i=x i=x,就有:
C m n x n = C q m q n x q n p C r m r n x r n C m n x n = C q m q n C r m r n x q n p + r n C m n x n = C q m q n C r m r n x n \begin{aligned}C_m^nx^n&=C_{q_m}^{q_n}x^{q_np}C_{r_m}^{r_n}x^{r_n}\\C_m^nx^n&=C_{q_m}^{q_n}C_{r_m}^{r_n}x^{q_np+r_n}\\C_m^nx^n&=C_{q_m}^{q_n}C_{r_m}^{r_n}x^n\end{aligned} CmnxnCmnxnCmnxn=CqmqnxqnpCrmrnxrn=CqmqnCrmrnxqnp+rn=CqmqnCrmrnxn
两边同乘 i n v ( x n ) inv(x^n) inv(xn),就有了 C m n = C q m q n C r m r n C_{m}^n=C_{q_m}^{q_n}C_{r_m}^{r_n} Cmn=CqmqnCrmrn

得证。

本题

其实逆元的话直接要用的话直接 x p − 2   m o d   p x^{p-2}\bmod p xp2modp 更好,不用像我这样线性求出每个。

代码

#include<cstdio>
#define ll long long

using namespace std;

ll T, n, m, p;
ll jc[100001], inv[100001];

ll ksm(ll x, ll y) {
	ll re = 1;
	while (y) {
		if (y & 1) re = (re * x) % p;
		x = (x * x) % p;
		y >>= 1;
	}
	return re;
}

ll C(ll x, ll y) {//暴力算组合数
	if (x > y) return 0;
	return ((jc[y] * inv[x]) % p * inv[y - x]) % p;
}

ll work(ll n, ll m) {//Lucas 定理
	if (!n) return 1;
	return (work(n / p, m / p) * C(n % p, m % p)) % p;
}

int main() {
	scanf("%lld", &T);
	while (T--) {
		scanf("%lld %lld %lld", &n, &m, &p);
		jc[0] = 1;
		for (ll i = 1; i <= p; i++)//预处理阶乘与其逆元
			jc[i] = (jc[i - 1] * i) % p;
		inv[p - 1] = ksm(jc[p - 1], p - 2);
		for (ll i = p - 2; i >= 0; i--)
			inv[i] = (inv[i + 1] * (i + 1)) % p;
		
		printf("%lld\n", work(n, n + m));
	}
	
	return 0;
}
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值