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;
}