扩展lucas定理

前置知识:

介绍

当正整数 n , m n,m n,m很大,且质数 p p p较小的时候,要求 C n m C_n^m Cnm p p p取模后的值,可以用lucas定理。

但如果 p p p不是质数,那该怎么办呢?如果 m m m较小,则可以用扩展lucas定理。

第一步:中国剩余定理

p = p 1 r 1 p 2 r 2 ⋯ p k r k p=p_1^{r_1}p_2^{r_2}\cdots p_k^{r_k} p=p1r1p2r2pkrk,其中 p i p_i pi为质数。我们可以先求出 C n m % p 1 r 1 , C n m % p 2 r 2 , … , C n m % p k r k C_n^m\%p_1^{r_1},C_n^m\%p_2^{r_2},\dots,C_n^m\%p_k^{r_k} Cnm%p1r1,Cnm%p2r2,,Cnm%pkrk的值 a 1 , a 2 , … , a k a_1,a_2,\dots,a_k a1,a2,,ak

我们把 C n m C_n^m Cnm看作未知数 x x x,可以得到以下方程组:

{ x ≡ a 1 ( m o d p 1 r 1 ) x ≡ a 2 ( m o d p 2 r 2 ) x ≡ a 3 ( m o d p 3 r 3 ) . . . . . . x ≡ a n ( m o d p k r k ) \left\{ \begin{matrix} x\equiv a_1\pmod{p_1^{r_1}}\\ x\equiv a_2\pmod{p_2^{r_2}}\\ x\equiv a_3\pmod{p_3^{r_3}}\\ ......\\ x\equiv a_n\pmod{p_k^{r_k}} \end{matrix} \right. xa1(modp1r1)xa2(modp2r2)xa3(modp3r3)......xan(modpkrk)

利用中国剩余定理,我们可以求出 x x x,它是以 p p p为周期出现的无穷多个解。而在 [ 0 , p ) [0,p) [0,p)这个周期的解,就是 C n m % p C_n^m\%p Cnm%p后的值。

那么 a 1 , a 2 … , a k a_1,a_2\dots,a_k a1,a2,ak怎么求呢?


第二步:组合数模质数的幂

由第一步可得

a = C n m   m o d   p r a=C_n^m\bmod p^r a=Cnmmodpr

因为 C n m = n ! m ! ( n − m ) ! C_n^m=\dfrac{n!}{m!(n-m)!} Cnm=m!(nm)!n!,我们若要求 m ! m! m! ( n − m ) ! (n-m)! (nm)!关于 p r p^r pr的逆元,则要把其中所有的质因子 p p p提出来,再乘回去即可。

C n m = n ! m ! ( n − m ) ! = n ! p x m ! p y × ( n − m ) ! p z × p x − y − z C_n^m=\dfrac{n!}{m!(n-m)!}=\dfrac{\frac{n!}{p^x}}{\frac{m!}{p^y}\times \frac{(n-m)!}{p^z}}\times p^{x-y-z} Cnm=m!(nm)!n!=pym!×pz(nm)!pxn!×pxyz

其中 x , y , z x,y,z x,y,z分别是 n ! , m ! , ( n − m ) ! n!,m!,(n-m)! n!,m!,(nm)!中质因子 p p p的次数。此时 m ! p y × ( n − m ) ! p z \dfrac{m!}{p^y}\times \dfrac{(n-m)!}{p^z} pym!×pz(nm)! p r p^r pr互质,可以直接求逆元。因为 C n m C_n^m Cnm为整数,所以 x − y − z ≥ 0 x-y-z\geq 0 xyz0 p x − y − z p^{x-y-z} pxyz可以用快速幂来求。


第三步:阶乘除去质因子后模质数幂

接下来的问题就是计算以下式子

n ! p t   m o d   p k \dfrac{n!}{p^t}\bmod p^k ptn!modpk

我们呢先考虑如如何计算 n !   m o d   p k n!\bmod p^k n!modpk。举个例子: n = 22 , p = 3 , k = 2 n=22,p=3,k=2 n=22,p=3,k=2

22 ! = 1 × 2 × 3 × 4 × 5 × 6 × 7 × 8 × 9 × 10 × 11 × 12 × 13 × 14 × 15 × 16 × 17 × 18 × 19 × 20 × 21 × 22 22!=1\times 2\times 3\times 4\times 5\times 6\times 7\times 8\times 9\times 10\times 11\times 12\times 13\times 14\times 15\times 16\times 17\times 18\times 19\times 20\times 21\times 22 22!=1×2×3×4×5×6×7×8×9×10×11×12×13×14×15×16×17×18×19×20×21×22

把其中 3 3 3的倍数提出来,得到

22 ! = ( 3 × 6 × 9 × 12 × 15 × 18 × 21 ) × ( 1 × 2 × 4 × 5 × 7 × 8 × 10 × 11 × 13 × 14 × 16 × 17 × 19 × 20 × 22 ) 22!=(3\times 6\times 9\times 12\times 15\times 18\times 21)\times (1\times 2\times 4\times 5\times 7\times 8\times 10\times 11\times 13\times 14\times 16\times 17\times 19\times 20\times 22) 22!=(3×6×9×12×15×18×21)×(1×2×4×5×7×8×10×11×13×14×16×17×19×20×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 ) \qquad =3^7\times (1\times 2\times 3\times 4\times 5\times 6\times 7)\times (1\times 2\times 4\times 5\times 7\times 8\times 10\times 11\times 13\times 14\times 16\times 17\times 19\times 20\times 22) =37×(1×2×3×4×5×6×7)×(1×2×4×5×7×8×10×11×13×14×16×17×19×20×22)

其中 3 7 3^7 37即为 p k p^k pk,就是需要被提出的部分。

对于 7 ! 7! 7!,即为 ⌊ n p ⌋ ! \lfloor \dfrac np\rfloor! pn⌋!,可以递归来求。

对于后面的部分,我们发现

1 × 2 × 4 × 5 × 7 × 8 ≡ 10 × 11 × 13 × 14 × 16 × 17 ( m o d p k ) 1\times 2\times 4\times 5\times 7\times 8\equiv 10\times 11\times 13\times 14\times 16\times 17\pmod{p^k} 1×2×4×5×7×810×11×13×14×16×17(modpk)

那么 1 × 2 × 4 × 5 × 7 × 8 1\times 2\times 4\times 5\times 7\times 8 1×2×4×5×7×8在整个式子中出现了 ⌊ n p k ⌋ \lfloor\dfrac{n}{p^k}\rfloor pkn次,因此,我们可以先计算在 p k p^k pk以内的部分,然后再求其 ⌊ n p k ⌋ \lfloor\dfrac{n}{p^k}\rfloor pkn次幂。不要忘了乘上最后多出的一部分。

1 × 2 × 4 × 5 × 7 × 8 × 10 × 11 × 13 × 14 × 16 × 17 × 19 × 20 × 22 ≡ ( 1 × 2 × 4 × 5 × 7 × 8 ) 3 × 19 × 20 × 22 ( m o d p k ) 1\times 2\times 4\times 5\times 7\times 8\times 10\times 11\times 13\times 14\times 16\times 17\times 19\times 20\times 22\equiv (1\times 2\times 4\times 5\times 7\times 8)^3\times 19\times 20\times 22\pmod{p^k} 1×2×4×5×7×8×10×11×13×14×16×17×19×20×22(1×2×4×5×7×8)3×19×20×22(modpk)

也就是说,对于以下式子

= 3 7 × ( 1 × 2 × 3 × 4 × 5 × 6 × 7 ) × ( 1 × 2 × 4 × 5 × 7 × 8 × 10 × 11 × 13 × 14 × 16 × 17 × 19 × 20 × 22 ) \qquad =3^7\times (1\times 2\times 3\times 4\times 5\times 6\times 7)\times (1\times 2\times 4\times 5\times 7\times 8\times 10\times 11\times 13\times 14\times 16\times 17\times 19\times 20\times 22) =37×(1×2×3×4×5×6×7)×(1×2×4×5×7×8×10×11×13×14×16×17×19×20×22)

3 7 3^7 37已经被提出了,不用计算。第二部分可以递归计算。第三部分可以 O ( p k ) O(p^k) O(pk)得出。


总结

扩展lucas定理与lucas定理在实现上并没有太大关联,只是解决的问题比较类似。扩展lucas定理的时间复杂度大概为 O ( p + log ⁡ 2 n ) O(p+\log^2 n) O(p+log2n)。当然,这是最坏的时间复杂度,一般的时间复杂度远远低于此。如果 p p p的质因子比较多且都比较小,则时间复杂度会降低很多。


例题

P4720 【模板】扩展卢卡斯定理

code

#include<bits/stdc++.h>
using namespace std;
int tot=0;
long long mod,x,y,ans=0,a[105],r[105];
long long mi(long long t,long long v,long long P){
	if(v==0) return 1;
	long long re=mi(t,v/2,P);
	re=re*re%P;
	if(v&1) re=re*t%P;
	return re;
}
void exgcd(long long c,long long d){
	if(d==0){
		x=1;y=0;
		return;
	}
	exgcd(d,c%d);
	long long t=x;x=y;y=t-c/d*y;
}
long long gt(long long v,long long p,long long q){
	if(!v) return 1;
	long long re=1;
	for(int i=1;i<=q;i++){
		if(i%p) re=re*i%q;
	}
	re=mi(re,v/q,q)%q;
	for(int i=1;i<=v%q;i++){
		if(i%p) re=re*i%q;
	}
	return re*gt(v/p,p,q)%q;
}//第三步
long long C(long long v1,long long v2,long long p,long long q){
	if(v1<v2) return 0;
	long long f1=gt(v1,p,q),f2=gt(v2,p,q),f3=gt(v1-v2,p,q),vt=0;
	for(long long i=p;i<=v1;i*=p) vt+=v1/i;
	for(long long i=p;i<=v2;i*=p) vt-=v2/i;
	for(long long i=p;i<=v1-v2;i*=p) vt-=(v1-v2)/i;
	return mi(p,vt,q)%q*f1%q*mi(f2,q-q/p-1,q)%q*mi(f3,q-q/p-1,q)%q;
}//第二步
int main()
{
	long long n,m,v;
	scanf("%lld%lld%lld",&n,&m,&mod);
	v=mod;
	for(int i=2;i*i<=v;i++){
		if(v%i==0){
			r[++tot]=1;
			while(v%i==0){
				r[tot]*=i;
				v/=i;
			}
			a[tot]=C(n,m,i,r[tot]);
		}
	}
	if(v>1){
		r[++tot]=v;
		a[tot]=C(n,m,v,v);
	}
	v=mod;
	for(int i=1;i<=tot;i++){
		exgcd(v/r[i],r[i]);
		x=(x%r[i]+r[i])%r[i];
		ans=(ans+v/r[i]*a[i]*x%v)%v;
	}//第一步
	printf("%lld",ans);
	return 0;
}
<think>嗯,用户想了解Lucas定理,涉及数学、计算机科学、组合数和取模运算。我需要先回忆一下Lucas定理的基本内容和应用场景。首先,Lucas定理是用来计算组合数取模的一个方法,特别是当模数是质数的时候。这个定理在组合数学和算法竞赛中应该比较常见,因为处理大数组合数取模的问题时,直接计算可能会非常耗时或者溢出,所以需要高效的算法。 根据用户提供的引用,特别是引用[3]提到数论是算法竞赛的重要部分,Lucas定理作为数论中的一个定理,可能在竞赛中用于解决组合数取模的问题。用户的问题涉及组合数和取模运算,所以需要详细说明定理的表述、证明思路以及实际应用方法。 首先,Lucas定理的具体内容是什么?我记得定理指出,对于质数p,将两个非负整数m和n表示为p进制展开,即m = m_k p^k + ... + m_0,n = n_k p^k + ... + n_0,那么组合数C(m, n) mod p等于各个对应位组合数C(m_i, n_i)的乘积再mod p。如果某一位的n_i > m_i,则整个组合数mod p为0。 接下来需要解释定理的数学表达式,用LaTeX写成独立公式。比如: $$ \binom{m}{n} \equiv \prod_{i=0}^k \binom{m_i}{n_i} \pmod{p} $$ 其中,m_i和n_i是m和n在p进制下的各位数字。这个表达式需要正确使用$$...$$格式,并且单独成段。 然后,定理的证明思路是怎样的?通常,证明会用到生成函数或者多项式展开,利用二项式定理在模p下的性质。例如,考虑多项式(1 + x)^m在模p下的展开,并分解为各个p进制位的乘积。这部分可能需要引用二项式定理Lucas的原始论文,但用户提供的引用中没有直接相关的,所以可能需要简要说明证明的大致步骤,而不过多深入细节。 应用场景方面,用户可能关心的是在算法竞赛中如何用Lucas定理快速计算组合数模质数的情况。例如,当需要计算C(n, k) mod p,其中p是质数,且n和k很大(比如1e18),这时候直接计算不可行,使用Lucas定理可以将问题分解为多个小规模的组合数计算,这些小组合数可以通过预计算阶乘和逆元来处理。 在步骤解释时,需要分步说明如何应用Lucas定理。例如: 1. 将n和k转换为p进制数。 2. 对每一位计算组合数C(n_i, k_i) mod p。 3. 将所有结果相乘再mod p得到最终结果。 可能还需要提到如何处理n_i < k_i的情况,这时候组合数为0,整个乘积也为0,因此直接返回0。 然后,给出一个具体的例子,比如计算C(12, 5) mod 3。将12和5转换为3进制,得到12=110_3,5=12_3。然后对应每一位的组合数:C(1,1)=1,C(1,2)=0(因为1<2),所以结果为1*0=0 mod 3。但这里可能需要注意位数对齐的问题,可能需要补前导零,比如5在3进制下是12,而12在3进制下是110,位数不同,所以需要将5补为012。然后每位组合数分别是C(1,0)=1,C(1,1)=1,C(0,2)=0,所以乘积是1*1*0=0。这个例子可能需要更详细地说明步骤,避免混淆。 接下来,可能需要给出代码示例,比如用递归或迭代的方式实现Lucas定理。代码部分需要用Python展示,并注意语法正确。例如,一个递归实现的Lucas函数,其中comb函数用于计算小规模的组合数mod p,可能需要预处理阶乘和逆元来提高效率。 此外,需要指出Lucas定理的限制,比如p必须是质数,如果p不是质数,则需要使用其他方法如中国剩余定理分解模数。这可能关联到引用[2]中提到的梅森素数判断中的模运算问题,但用户的问题中没有提到,所以可能不需要深入展开。 最后,生成相关问题需要考虑用户可能的后续疑问,比如Lucas定理扩展应用、与其他定理(如中国剩余定理)的结合使用、处理非质数模数的方法、算法的时间复杂度以及优化技巧等。例如: 1. Lucas定理能否处理模数为合数的情况? 2. 如何结合中国剩余定理处理大数组合数取模? 3. 有没有比Lucas定理更高效的组合数取模算法? 4. Lucas定理的递归实现和迭代实现哪种更好? 需要确保这些问题与Lucas定理相关,并且能引导用户进一步深入学习。 总结,回答的结构应该包括定理的表述、证明思路、应用方法、实例演示、代码实现、应用场景以及相关问题。需要确保所有数学公式正确使用$...$或$$...$$,引用文献适当,并且回答符合用户要求的结构清晰和真实可靠。</think>### Lucas定理详解 Lucas定理是数论中用于高效计算组合数取模的重要工具,尤其适用于模数$p$为质数的情况。其核心思想是将大数分解为$p$进制各位的组合数乘积,从而降低计算复杂度[^3]。 #### 定理表述 设$p$为质数,$m,n$为非负整数,将其表示为$p$进制展开: $$ m = m_kp^k + m_{k-1}p^{k-1} + \dots + m_0 \\ n = n_kp^k + n_{k-1}p^{k-1} + \dots + n_0 $$ 则组合数满足: $$ \binom{m}{n} \equiv \prod_{i=0}^k \binom{m_i}{n_i} \pmod{p} $$ 若存在某位$n_i > m_i$,则$\binom{m}{n} \equiv 0 \pmod{p}$[^1]。 #### 证明思路 1. **多项式展开**:利用二项式定理展开$(1+x)^m$,在模$p$环境下分析系数 2. **生成函数分解**:将$(1+x)^m$分解为$p$进制各位的乘积形式 3. **系数对应**:通过比较系数得到组合数的分解关系 #### 应用步骤 以计算$\binom{12}{5} \mod 3$为例: 1. **转换进制**:$12=1\cdot3^2 + 1\cdot3^1 + 0\cdot3^0$,$5=0\cdot3^2 +1\cdot3^1 +2\cdot3^0$ 2. **逐位计算**: - $\binom{1}{0}=1$ - $\binom{1}{1}=1$ - $\binom{0}{2}=0$ 3. **结果相乘**:$1\times1\times0 \equiv 0 \mod 3$ #### 代码实现 ```python def comb(n, k, p): if k > n: return 0 # 预计算阶乘和逆元更高效 numerator = 1 for i in range(k): numerator = numerator * (n-i) % p denominator = 1 for i in range(1, k+1): denominator = denominator * i % p return numerator * pow(denominator, p-2, p) % p # 费马小定理求逆元 def lucas(n, k, p): if k == 0: return 1 return comb(n%p, k%p, p) * lucas(n//p, k//p, p) % p ``` #### 应用场景 - **算法竞赛**:处理$n,k$极大(如$10^{18}$)的组合数取模问题 - **密码学**:构造特定数学结构的加密算法 - **概率计算**:大样本空间下的离散概率计算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值