Lucas 定理学习笔记

一、定理

给定 n,m,pp 是质数,求 Cm+nnmodpn,m1018,p106
这题可以用 Lucas 定理求解。
Lucas 定理:
p 是个质数时,m,nN,CnmCnpmp×Cnmodpmmodp(modp)

要证明这个结论,要先证明一个引理:
p 是个质数时,(1+x)p1p+xp(modp)
为什么?我们知道,n[0,p],Cpn=p!n!×(pn)!。由于 p 是个质数,所以分子的质因数中有且仅有 1 个 p

  1. n=0n=p 此时分母也有 1 个 p,并且 Cpn=1
  2. 0<n<p,此时分母没有质因数 p,所以此时 Cpn0(modp)

然后我们用二项式定理拆开:
(1+x)pi=0pCpi×1pi×xi
i=0pCpi×xi
Cp0×x0+Cpp×xp
1+xp(modp)
这样,引理就证完了。

然后就是 Lucas 定理了。

我们知道,Cnm 可以代表 (1+x)nm 次项的系数。
假设 n=a×p+b,m=c×p+d,b,d[0,p1]
那么 (1+x)n(1+x)a×p×(1+x)b
((1+x)p)a×(1+x)b
(1+xp)a×(1+x)b

然后考虑 m 次项的系数,
CnmxmCacxp×c×Cbdxd(modp)
所以就知道 CnmCac×Cbd(modp)
也就是 CnmCnpmp×Cnmodpmmodp(modp)。□

时间复杂度:预处理 O(p),单次计算 O(logp)

二、代码

inline void exgcd(ll &x,ll &y,ll a,ll b){
	if(!b){x=1;y=0;return;}
	exgcd(y,x,b,a%b);y-=a/b*x;
}
inline ll lucas(ll x,ll y){
	if(x<y)return 0;
	if(x<p)return a[x]*b[y]*b[x-y]%p;
	return lucas(x/p,y/p)*lucas(x%p,y%p)%p;
}
int main(){
	cin>>t;a[0]=b[0]=a[1]=b[1]=1;
	while(t--){
		cin>>n>>m>>p;
		for(ll i=2;i<p;i++)a[i]=a[i-1]*i%p;
		for(ll i=2;i<p;i++)b[i]=(p-p/i)*b[p%i]%p;
		for(ll i=2;i<p;i++)b[i]=b[i-1]*b[i]%p;
		cout<<lucas(n+m,n)<<'\n'; 
	}
	return 0;
}

三、推论

Cnm 是质数 p 的倍数当且仅当 np 进制下有一位小于 m

证明:假设 (n)p=a0a1ab,(m)p=c0c1cd
那么反复使用 Lucas 定理,知 Cnmi=0max{b,d}Caici,多余位补 0

然后如果存在 ck>ak,则 Cakck0(modp),所以 Cnmi=0max{b,d}Caici0(modp)

如果 i[0,max{b,d}],都有 aici,那么由于 ciai<p,所以 gcd(Caici,p)=1,所以 Cnm0(modp)。□

posted @   lrxQwQ  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示