Lucas 定理

Lucas 定理

\[C_m^n \equiv C_{m \bmod p}^{n \bmod p} \cdot C_{\lfloor \frac{m}{p} \rfloor}^{\lfloor \frac{n}{p} \rfloor} \pmod{p} \]

证明

规定:\(inv_x\) 表示 \(x\) 在模 \(p\) 意义下的逆元

定理 1

\(C_p^x \equiv p \times inv_x \times C_{p-1}^{x-1} \equiv 0 \pmod p (0<x<p)\)

证明:

\[C_p^x = \frac{p!}{x!(p-x)!} = \frac{p \cdot (p-1)!}{x \cdot (x-1)!(p-x)!} = \frac{p}{x} \cdot \frac{(p-1)!}{(x-1)![(p-1)-(x-1)]!} = \frac{p}{x} \cdot C_{p-1}^{x-1} \equiv p \cdot inv_x \cdot C_{p-1}^{x-1} \pmod{p} \]

定理 2

\((1+x)^p \equiv 1+x^p \pmod{p}\)

根据二项式定理

\[(1+x)^p = \sum\limits_{i=0}^p C_p^i \cdot x^i \cdot 1^{p-i} \\ = \sum\limits_{i=0}^p C_p^i \cdot x^i \\ \because C_p^x \equiv p \cdot inv_x \cdot C_{p-1}^{x-1} \equiv 0 \pmod{p} (0<x<p) \\ \therefore (1+x)^p = C_p^0 \cdot x^0 + C_p^p \cdot x^p \\ = 1 + x^p \]

推 式 子

\(\left\{ \begin{matrix} s = \lfloor \frac{m}{p} \rfloor \\ r = m \bmod p \\ \end{matrix} \right.\),则 \(m=sp+r\)

\[\because (1+x)^m = \sum\limits_{k=0}^{m} C_m^k x^k \\ \therefore (1+x)^m = (1+x)^{sp+r} = (1+x)^{sp} \cdot (1+x)^r \\ = [(1+x)^p]^s \cdot (1+x)^r \\ \equiv (1+x^p)^s \cdot (1+x)^r \pmod{p} \\ = \sum\limits_{i=0}^s C_s^i x^{ip} \cdot \sum\limits_{j=0}^r C_r^j x^j \\ = \sum\limits_{i=0}^s \sum\limits_{j=0}^r C_s^i C_r^j x^{ip+j} \]

因为 \(ip+j\) 刚好会枚举到 \([0,m]\) 中的整数各一次(对于每个在 \([0,m]\) 中的整数 \(x\) 都可以拆成 \(\lfloor \frac{x}{p} \rfloor \cdot p + x \bmod p\) 的形式,而 \(i = \lfloor \frac{x}{p} \rfloor,j = x \bmod p\)),所以转而枚举 \(k=ip+j\)

\[(1+x)^m \equiv \sum\limits_{k=0}^m C_s^{\lfloor \frac{k}{p} \rfloor} C_r^{k \bmod p} \pmod{p} \]

\(k=n\),则

\[C_m^n \equiv C_s^{\lfloor \frac{n}{p} \rfloor} \cdot C_r^{n \bmod p} = C_{m \bmod p}^{n \bmod p} \cdot C_{\lfloor \frac{m}{p} \rfloor}^{\lfloor \frac{n}{p} \rfloor} \pmod{p} \]

得证.

代码实现

例题:洛谷 P3807 【模板】卢卡斯定理

如果寻求高效率,建议先预处理出 \(0\)~\(p\) 在模 \(p\) 意义下的逆元和 \(0\)~\(p\) 的阶乘:

for(int i=2;i<=p;i++)
{
      fac[i]=1ll*fac[i-1]*i%p;
      inv[i]=1ll*(p-p/i)*inv[p%i]%p;
}

然后再处理出 \(0\)~\(p\) 的阶乘的逆元:

for(int i=2;i<=p;i++)
      inv[i]=1ll*inv[i-1]*inv[i]%p;
//注意不能和求0~p的逆元放一起做!!!

然后就是快快乐乐的 \(Lucas\) 了:

int C(int _m,int _n,int mod)
{
	if(_n>_m) return 0;
	return 1ll*fac[_m]*inv[_n]%mod*inv[_m-_n]%mod;
}
int Lucas(int _m,int _n,int mod)
{
	if(_n==0){return 1;}
	else return 1ll*C(_m%mod,_n%mod,mod)*Lucas(_m/mod,_n/mod,mod)%mod;
}
posted @ 2021-01-16 21:12  Mine_King  阅读(165)  评论(0编辑  收藏  举报