Lucas定理以及证明

对着无数篇博客终于\(yy\)懂了\(Lucas\)定理,兴奋之际赶紧写下来

内容

如果\(p\)是质数,那么\(C_{n}^{m}\equiv C_{n\mod p}^{m\mod p}\times C_{n/p}^{m/p}(mod\ p)\)

证明

首先我们要知道一个性质:

如果\(p\)为质数,那么有\(C_{p}^{n}\equiv 0(mod\ p)\),其中\(n\ne 0,p\)

这个很显然吧,考虑把组合数的式子写出来:\(C_p^n=\frac{p!}{n!(p-n)!}\)

\(p\)提出来就变成了\(\frac{(p-1)!}{n!(p-n)!}\times p\),就证完了

这个性质有什么用呢?别着急,我们先往下走

二项式定理得:\((x+1)^p=\sum _{i=0}^{p}C_p^i\times x^i\)

而根据上面的性质,因为\(n\)只有在等于\(0\)\(p\)时才为\(1\),其余时都为\(0\)得到在模\(p\)意义下

\[(x+1)^p\equiv x^p+1(mod\ p) \]

\(n=\left \lfloor \frac{n}{p} \right \rfloor\times p+n\ mod \ p\)

那么可得\((x+1)^n\equiv (x+1)^{\left \lfloor \frac{n}{p} \right \rfloor\times p}+(x+1)^{n\ mod\ p}(mod\ p)\)

替换得\((x+1)^n\equiv (x^p+1)^{\left \lfloor \frac{n}{p} \right \rfloor}+(x+1)^{n\ mod\ p}(mod\ p)\)

根据二项式定理,展开得

\[\sum_{i=0}^{n}C_n^i\times x^i\equiv \sum_{j=0}^{\left \lfloor \frac{n}{p} \right \rfloor}C_{\left \lfloor \frac{n}{p} \right \rfloor}^j\times x^j+\sum_{k=0}^{n\ mod\ p}C_{n\ mod\ p}^{k}\times x^k(mod\ p) \]

观察这个式子,我们发现对于每一个\(i\),都一定存在\(j,k\)与其对应,保证\(x^i=x^j\times x^k\),约掉之后就是\(Lucas\)

证毕

代码很好写,丢下板子题代码QAQ

#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
int t,m,n,p;
int mypow(int a,int x)
{
	int s=1;
	while (x)
	{
		if (x&1)s=s*a%p;
		a=a*a%p;
		x>>=1;
	}
	return s;
}
int C(int m,int n)
{
	if (m>n)return 0;
	int a=1,b=1;
	for (int i=1;i<=n;i++)a=a*i%p;
	for (int i=1;i<=m;i++)b=b*i%p;
	for (int i=1;i<=n-m;i++)b=b*i%p;
	return a*mypow(b,p-2)%p;
}
int lucas(int m,int n)
{
	if (!m)return 1;
	return C(m%p,n%p)*lucas(m/p,n/p)%p;
}
signed main()
{
	cin>>t;
	while (t--)
	{
		cin>>n>>m>>p;
		cout<<lucas(m,m+n)<<endl; 
	} 
	return 0;
}

扩展\(Lucas\)感觉实际用途比较少,而且复杂度可能不太对,就不放了

原文地址:https://www.cnblogs.com/sdlang/p/13068048.html