Lucas 定理

lucas 定理用于求解模数很\(**\)的组合数求解,比如模小素数,会遇到不一定互质即没有逆元的情况。

\[C_{n}^m\equiv C_{n/p}^{m/p}C_{n\bmod p}^{m\bmod p} \]

或者说 \((n_i,m_i)\)\((n,m)\)\(p\) 进制上的一组,\(C_{n_i}^{m_i}\) 的积就是答案力(((


因为你可能想问为什么,所以原神会告诉你答案。

我们要求解 \(C_n^m\bmod p\),我们设 \(n=ap+b,m=cp+d\),其中 \(0\leq b,d<p\)

我们要证明的是 \(C_n^m=C_a^bC_c^d\pmod p\)

根据二项式定理,\(C_n^m\)\((1+x)^n\)\(x^m\) 的系数是相等的。

我们在 \(\bmod p\) 意义下进行推导:

\[(1+x)^n\equiv(1+x)^{ap+b}\equiv((1+x)^p)^a(1+x)^b \]

对于 \(C_p^i=\frac{p!}{i!(p-i)!}\),只有当 \(i=0,p\) 的时候取到 \(1\),其它时候都是 \(p\) 的倍数。 我们把 \((1+x)^p\) 展开,在 \(\bmod p\) 的情况下其实只剩下 \(1+x^p\) 了,继续推导 qwq

\[((1+x)^p)^a(1+x)^b\equiv (1+x^p)^a(1+x)^b\equiv\sum_{i=0}^aC_a^ix^{pi}\sum_{j=0}^bC_b^jx^j \]

我们再次回看 \(x^m\) 的系数,你不是 \(m=cp+d\) 嘛,那是不是等于 \(C_a^cC_b^d\),赢!

int p, mul[MN], inv[MN]; 
mul[0]=inv[0]=1;
mul[1]=inv[1]=1;
for(int i=2; i<p; ++i) mul[i]=mul[i-1]*i%p;
for(int i=2; i<p; ++i) inv[i]=inv[p%i]*(p-p/i)%p;
for(int i=2; i<p; ++i) inv[i]=inv[i-1]*inv[i]%p;
int c(int a,int b,int p) {
	if(a<b) return 0;
	return (mul[a]*inv[b]%p)*inv[a-b]%p;
}
int lucas(int a,int b,int p) {
	if(b==0) return 1;
	int lucas(a/p,b/p,p)*c(a%p,b%p,p)%p;
}

不想递归的话,可以这么写 qwq

int lucas(int a,int b,int p) {
	if(a<b) return 0;
	int res=1;
	for( ; a; a/=p, b/=p)
		res=res*c(a%p,b%p,p)%p;
	return res;
}
posted @ 2023-08-12 22:56  Hypoxia571  阅读(36)  评论(0编辑  收藏  举报