1.1 问题引入

已知\(p\)是一质数,求\(\dbinom{n}{m}\pmod{p}\).

关于组合数,它和排列数都是组合数学中的重要概念.这里会张贴有关这两个数的部分内容.

由于Lucas定理比较简单粗暴,这里直接给出表达式:

\[\boxed{\dbinom{n}{m}\equiv\dbinom{n\mod p}{m\mod p}\dbinom{\frac{n}{p}}{\frac{m}{p}}\pmod{p}}$$.
或者:
$$\boxed{\dbinom{n}{m}\equiv \dbinom{n_1}{m_1}\dbinom{n_2}{m_2}\dots\dbinom{n_k}{m_k} \pmod{p}}\]

其中\(n=(n_1n_2\dots n_k)_p\),\(m=(m_1m_2\dots m_k)_p\),即\(n_i\)和\(m_i\)都是\(n\),\(m\)的\(p\)进制表示.

上面的公式其实是下面公式的递归版.仿照二进制,\(n \text{ div } p = (n_1n_2n_3\dots n_{k-1}n_k)_p \text{ div } p = (0n_1n_2\dots n_{k-1})_p\),相当于整个序列右移1位.而\(n \pmod{p}=n_k\),就是取出序列的最后一位.我们来证明一下这个定理.

我们把\(n\)的序列最后一项单独抠出来,\(n\)可以表示成\(n=\lfloor\frac{n}{p}\rfloor p + n\mod{p}=(n_1n_2\dots n_{k-1}0)_p+n_k\).

为了方便证明,我们把组合数套到二项式定理里面去.以下同余式均在模p意义下进行.

我们构造一个函数\(G_n(x)=(1+x)^n = \sum_{i=0}^n \dbinom{n}{i}x^i1^{n-i} = \sum_{i=0}^n \dbinom{n}{i}x^i\)

似乎这个函数和所谓的生成函数有关.

\(G_p(x)\equiv (1+x)^p \equiv \sum_{i=0}^p \dbinom{p}{i}x^i \equiv 1+ \sum_{i=1}^{p-1}\dbinom{p}{i}x^i + x^p\)

由于当\(i \neq 0 , p\)时,有\(\dbinom{p}{i} \equiv \dfrac{p!}{i!(p-i)!} \equiv p \dfrac{(p-1)!}{i!(p-i)!} \equiv 0\)

此时原式中间的那一大项式子可以直接消去,有:\((1+x)^p \equiv 1+x^p\).

由费马小定理,\((1+x)^p \equiv 1+x \pmod{p}\).

再结合上面的结论推到一下\(G_n(x)\)的表达式:

\(G_n(x)\equiv (1+x)^n \equiv (1+x)^{\lfloor\frac{n}{p}\rfloor p + n\pmod{p}}\)

\(\equiv (1+x)^{\lfloor\frac{n}{p}\rfloor}(1+x)^{n\pmod{p}}\)

\(\equiv (1+x^p)^{\lfloor\frac{n}{p}\rfloor}(1+x)^{n\pmod{p}}\)

\(\equiv \sum_{i=0}^{\lfloor\frac{n}{p}\rfloor}\dbinom{\lfloor\frac{n}{p}\rfloor}{i}(x^{p})^{i} \cdot \sum_{i=0}^{n\pmod{p}}\dbinom{n\pmod{p}}{i}x^i\)

\(\equiv G_{\lfloor\frac{n}{p}\rfloor}(x^p)\cdot G_{n\pmod{p}}(x)\)

其中函数\(G_s(x)\)中浓缩了一串数列:\(\{\dbinom{s}{0},\dbinom{s}{1},\dots,\dbinom{s}{s}\}\),每一项\(\dbinom{s}{i}\)是函数中\(x^i\)的系数.

因此,函数\(G_n(x)\)中\(x^k\)的系数是\(\dbinom{n}{k}\),假设复合函数\(G_{\lfloor\frac{n}{p}\rfloor}(x^p)\cdot G_{n\pmod{p}}(x)\)中包含\(x^k\)的一项可以写成:

\(a_kx^k=\dbinom{\lfloor\frac{n}{p}\rfloor}{u}(x^{p})^{u}\dbinom{n\pmod{p}}{v}x^v=\dbinom{\lfloor\frac{n}{p}\rfloor}{u}\dbinom{n\pmod{p}}{v}x^{pu+v} \qquad (※)\)

则必然有\(pu+v=k\).

同样的,我们取\(u=\lfloor\frac{k}{p}\rfloor\),\(v=k\pmod{p}\)

带入\((※)\)式:\(a_kx^k=\dbinom{\lfloor\frac{n}{p}\rfloor}{\lfloor\frac{k}{p}\rfloor}\dbinom{n\pmod{p}}{k\pmod{p}}x^k\).

我们就得到了一个新的函数$$H_n(x)=G_{\lfloor\frac{n}{p}\rfloor}(x^p)\cdot G_{n\pmod{p}}(x)=\sum_{i=1}{n}\dbinom{\lfloor\frac{n}{p}\rfloor}{\lfloor\frac{i}{p}\rfloor}\dbinom{n\pmod{p}}{i\pmod{p}}xi$$.

由上面的推论,在模\(p\)意义下,\(H_n(x) \equiv G_n(x)\)恒成立,所以对于每一项\(x^m\),其系数均有:\(\dbinom{n}{m}\equiv \dbinom{\lfloor\frac{n}{p}\rfloor}{\lfloor\frac{m}{p}\rfloor}\dbinom{n\pmod{p}}{m\pmod{p}}\)

2.1 拓展

对于\(p\)不是质数的情况,我们可以对p进行质因数分解:\(p=\prod_{i=1}^{k}p_i^{c_i}\)

那么原问题就变成了求解\(x=\dbinom{n}{m}\mod{(\prod_{i=1}^{k}p_i^{c_i})}\)

注意到每个\(p_i^{c_i}\)都必定是两两互素的数,我们先求\(\dbinom{n}{m}\pmod{p_i^{c_i}}\),则原来的问题就变成了:$$\begin{cases}x\equiv \dbinom{n}{m} \pmod{p_1^{c_1}}\x\equiv \dbinom{n}{m} \pmod{p_2^{c_2}}\\cdots\x\equiv \dbinom{n}{m} \pmod{p_k^{c_k}}\end{cases}$$

我们的问题就变成了求解这个同余方程组。利用中国剩余定理,我们知道最后解的形式一定是\(x\equiv x_0 \pmod{(\prod_{i=1}^{k}p_i^{c_i})}\)。用中国剩余定理求出方程组的特解\(x_0\)就可以了。

如果求\(\dbinom{n}{m}\mod p_i^{c_i}\),可以直接用阶乘计算:

\(\dbinom{n}{m}\mod{p_i^{c_i}}=\dfrac{n!\mod p_i^{c_i}}{(m!\mod{p_i^{c_i}})((n-m)!\mod{p_i^{c_i}})}\)

问题就是如何快速计算\(x!\mod{p_i^{c_i}}\)。

我们把阶乘的每一项展开来:\(x!=\prod_{k=1}^x{k}\)

试着每次从阶乘项里面提出\(p_i\)的倍数,进行计算:

\(x!=(p_i\cdot 2p_i\cdot 3p_i \cdots sp_i) \prod\limits_{1\leq k \leq x , p_i\nmid k}k\)

\(=p_i^s(s!)\prod\limits_{1\leq k \leq x , p_i\nmid k}k\)

由于模的循环性质,有:\(\prod\limits_{1\leq k \leq p_i^{c_i}}k\equiv \prod\limits_{p_i^{c_i} \leq k \leq 2p_i^{c_i}}k \equiv \cdots \pmod{p_i^{c_i}}\)

这样的循环节一共有\(\lfloor \frac{x}{p_i^{c_i}} \rfloor\)个。剩下的\(x-\lfloor \frac{x}{p_i^{c_i}} \rfloor\)就直接暴力计算就可以了。这有一点点分块的味道。

对于每一个循环节,我们只需要暴力计算其中一个\(p_i^{c_i}\)的部分,剩余的部分的答案是一样的。

典型地,我们采用网上流行的\(19!\mod 3^2\)来演示一下。

\(19!\equiv 1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19\)

\(\equiv (1*2*4*5*7*8)*(10*11*13*14*16*17)*(19)*(3*6*9*12*15*18)\)

\(\equiv (1*2*4*5*7*8)*(1*2*4*5*7*8)*(1)*3^6(1*2*3*4*5*6)\)

这里出现了两个循环节和一个剩余的数。快速幂+暴力求出前面部分的值,后面\(3^6\)可以指数相减,阶乘可以递归处理。

每算一个\(n!\mod p_i^{c_i}\)时间复杂度是\(O(p_i^{c_i}\log n(\log_{p_i}n-c_i))\)。

这里就不加处理地粘贴了洛谷模板题

#include<bits/stdc++.h>
#define RP(i,a,b) for(register int i=a;i<=b;++i)
#define DRP(i,a,b) for(register int i=a;i>=b;--i)
#define fre(z) freopen(z".in","r",stdin),freopen(z".out","w",stdout)
#define mem(a,b) memset(a,b,sizeof(a))
#define prique priority_queue
#define rg register
#include<cstdlib>
#include<ctime>
#ifdef WIN32
#define OT "%I64d"
#else
#define OT "%lld"
#endif
using namespace std;
typedef long long ll;
typedef double db;
template<class T> T qr(T type)
{
char ch=getchar();T ret=0;T q=1,res=1;
while(!isdigit(ch))
q=(ch=='-'?-1:q),ch=getchar();
while(isdigit(ch))
ret=ret*10+ch-'0',ch=getchar();
if(ch=='.')
{
ch=getchar();
while(isdigit(ch))
ret=ret*10+ch-'0',res=res*10,ch=getchar();
}
return q==-1?-ret/res:ret/res;
} ll n,m,P; inline ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1,y=0;
return a;
}
ll d=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return d;
} inline void put(ll x)
{
if(x<0)
x=-x,putchar('-');
if(x>=10)
put(x/10);
putchar(x%10+'0');
} inline ll qp(ll x,ll p,ll mod)
{
ll ans=1;
while(p)
{
if(p&1)
ans=(ans*x)%mod;
x=(x*x)%mod,p>>=1;
}
return ans;
} ll MF(ll n,ll p,ll pc)//compute n! by pc norm
{
if(n==0)
return 1;
ll res=1;
for(rg ll i=2;i<=pc;++i)
if(i%p)//don't compute the p factor for it has been computed out of the function.
res=(res*i)%pc;//compute the single recurring period
res=qp(res,n/pc,pc);//compute the all recurring period
for(rg ll i=2;i<=n%pc;++i)//compute the res num. out of recper.
if(i%p)
res=(res*i)%pc;
return res*MF(n/p,p,pc)%pc;
} inline ll inver(ll n,ll mod)
{
ll x,y;
exgcd(n,mod,x,y);
return (x+=mod)>mod?x-mod:x;
} inline ll C(ll n,ll m,ll p,ll pc)
{
ll fc_n=MF(n,p,pc),fc_m=MF(m,p,pc),fc_del=MF(n-m,p,pc);//n!,m!,(n-m)! by pc norm
ll d=0;
for(rg ll i=n;i>0;i/=p)
d+=i/p;//d(n!)
for(rg ll i=m;i>0;i/=p)
d-=i/p;//d(m!)
for(rg ll i=n-m;i>0;i/=p)
d-=i/p;//d((n-m)!)
//k=d(n!)-d(m!)-d((n-m)!)
//d(n) is the fac p's num in n
return fc_n*qp(p,d,pc)%pc*inver(fc_m,pc)%pc*inver(fc_del,pc)%pc;
} inline ll CRT(ll b,ll mod)
{
return b*inver(P/mod,mod)%P*(P/mod)%P;
}//add ans:aiMiti /*
suppose P=\prod(p_i^{c_i})
the origin equation x=C(n,m)(mod P) is equivalance to:
{x=C(n,m)(mod p_i^{c_i})} for each factor is perpendicular
then we can solve the subans in turn and combine them.
ans=\sum_{i=1}^{n}{a_i M_i t_i}
M_i = P/(p_i^{c_i})
t_i is the inversion of M_i by p_i^{c_i} norm */ inline ll exlucas(ll n,ll m)//main function
{
ll res=0,cur=P,pc;
ll Sqr=sqrt(P)+5;
for(rg ll i=2;i<=Sqr;++i) //limit the searching range:sqrt(n) technique
{
if(cur%i==0)// i|cur
{
pc=1;
while(cur%i==0)
pc*=i,cur/=i;//p_i=i,p_i^{c_i}=pc
res=(res+CRT(C(n,m,i,pc),pc))%P;
}
}
if(cur>1)//cur=sqrt(P)
res=(res+CRT(C(n,m,cur,cur),cur))%P;
return res;
} int main()
{
//fre("P4720");
n=qr(1ll),m=qr(1ll),P=qr(1ll);
put(exlucas(n,m));
return 0;
}

2.2 证明中出现的一些重要推论

阶乘\(n!\)中含有某个素因子\(p\)的个数\(\text{d}_p(x)\)。我们可以根据上面的过程,得到一个递归公式:

\[ \text{d}_p(x)=\text{d}_p(\lfloor \frac{x}{p} \rfloor)+ \lfloor \frac{x}{p} \rfloor \tag{1}
\]

展开这个递归式可以得到\(\text{d}_p(x)\)的计算公式:

\[ \text{d}_p(x)=\sum_{p^k \leq x} \lfloor \frac{x}{p^k} \rfloor \tag{1'}
\]

Lucas定理初探的更多相关文章

  1. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  2. CF451E Devu and Flowers (隔板法 容斥原理 Lucas定理 求逆元)

    Codeforces Round #258 (Div. 2) Devu and Flowers E. Devu and Flowers time limit per test 4 seconds me ...

  3. 大组合数:Lucas定理

    最近碰到一题,问你求mod (p1*p2*p3*……*pl) ,其中n和m数据范围是1~1e18 , l ≤10 , pi ≤ 1e5为不同的质数,并保证M=p1*p2*p3*……*pl ≤ 1e18 ...

  4. 【BZOJ-4591】超能粒子炮·改 数论 + 组合数 + Lucas定理

    4591: [Shoi2015]超能粒子炮·改 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 95  Solved: 33[Submit][Statu ...

  5. 组合数取模Lucas定理及快速幂取模

    组合数取模就是求的值,根据,和的取值范围不同,采取的方法也不一样. 下面,我们来看常见的两种取值情况(m.n在64位整数型范围内) (1)  , 此时较简单,在O(n2)可承受的情况下组合数的计算可以 ...

  6. hdu 3037 Saving Beans Lucas定理

    Saving Beans Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  7. 【BZOJ1951】【SDOI2010】古代猪文 Lucas定理、中国剩余定理、exgcd、费马小定理

    Description “在那山的那边海的那边有一群小肥猪.他们活泼又聪明,他们调皮又灵敏.他们自由自在生活在那绿色的大草坪,他们善良勇敢相互都关心……” ——选自猪王国民歌 很久很久以前,在山的那边 ...

  8. 组合数(Lucas定理) + 快速幂 --- HDU 5226 Tom and matrix

    Tom and matrix Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=5226 Mean: 题意很简单,略. analy ...

  9. HDU 4349 Xiao Ming's Hope lucas定理

    Xiao Ming's Hope Time Limit:1000MS     Memory Limit:32768KB  Description Xiao Ming likes counting nu ...

随机推荐

  1. # 江西CCPC省赛-Rng(概率+逆元)

    江西CCPC省赛-Rng(概率+逆元) 题意: 给出一个n,在[1,n]之间选一个R1,在[1,R1]之间选一个L1,得到区间[L1,R1],同理获取区间[L2,R2],问两个区间相交的概率对1e9+ ...

  2. # 数字签名&数字证书

    目录 数字签名&数字证书 数字签名 数字证书 数字证书的实例(https协议) 数字签名&数字证书 参考资料: 数字签名是什么?-阮一峰的网络日志 数字签名和数字证书究竟是什么?知乎- ...

  3. 14款CSS3图片层叠切换动画

    在线演示 本地下载

  4. oa_mvc_easyui_分页(4)

    1.数据层的编写 NewListInfoDal.cs: GetPageEntityList方法,根据start,end取出数据 --row_number() over()函数查询 LoadEntity ...

  5. oa_mvc_easyui_登录完成(2)

    1.使用MVC特有的ajax方式:异步表单提交方式 js文件引用:<script src="~/Scripts/jquery.unobtrusive-ajax.min.js" ...

  6. k-means 非监督学习聚类算法

    非监督学习 非监督学习没有历史样本数据和标签,直接对数据分析或得结果. k-means 使用 >>> from sklearn.cluster import KMeans >& ...

  7. 数据绘图工具之Matplotlib

    一.安装:绘图和可视化 pip install matplotlib 我们已经下好了anaconda 包含了绘图工具包 直接导入即可 import matplotlib.pyplotlib as pl ...

  8. 图书管理系统UML建模

    图书管理系统UML建模 用例图 借阅者请求服务用例图 图书管理员处理借书还书用例图 系统管理员系统维护用例图 时序图 系统管理员添加书籍时序图 协作图 借阅者预留书籍协作图 状态图 书的状态图 活动图 ...

  9. shell 实用脚本

    功能 将当前目录下文件拷贝至另一目录下,且拷贝前先备份 #!/bin/sh #脚本功能 #覆盖文件前先备份 cfsuffix=$(date +%Y%m%d); #备份文件后缀 ]; then #输入参 ...

  10. 手动写一个类支持foreach循环

    之前初学时看过可以实现Iterable接口实现Iterator迭代器的支持,并且也支持foreach循环.现在学习了数据结构,手动写一个单链表支持foreach循环吧. 手写foreach循环步骤: ...