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))\)。

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

  1. #include<bits/stdc++.h>
  2. #define RP(i,a,b) for(register int i=a;i<=b;++i)
  3. #define DRP(i,a,b) for(register int i=a;i>=b;--i)
  4. #define fre(z) freopen(z".in","r",stdin),freopen(z".out","w",stdout)
  5. #define mem(a,b) memset(a,b,sizeof(a))
  6. #define prique priority_queue
  7. #define rg register
  8. #include<cstdlib>
  9. #include<ctime>
  10. #ifdef WIN32
  11. #define OT "%I64d"
  12. #else
  13. #define OT "%lld"
  14. #endif
  15. using namespace std;
  16. typedef long long ll;
  17. typedef double db;
  18. template<class T> T qr(T type)
  19. {
  20. char ch=getchar();T ret=0;T q=1,res=1;
  21. while(!isdigit(ch))
  22. q=(ch=='-'?-1:q),ch=getchar();
  23. while(isdigit(ch))
  24. ret=ret*10+ch-'0',ch=getchar();
  25. if(ch=='.')
  26. {
  27. ch=getchar();
  28. while(isdigit(ch))
  29. ret=ret*10+ch-'0',res=res*10,ch=getchar();
  30. }
  31. return q==-1?-ret/res:ret/res;
  32. }
  33. ll n,m,P;
  34. inline ll exgcd(ll a,ll b,ll &x,ll &y)
  35. {
  36. if(b==0)
  37. {
  38. x=1,y=0;
  39. return a;
  40. }
  41. ll d=exgcd(b,a%b,y,x);
  42. y-=(a/b)*x;
  43. return d;
  44. }
  45. inline void put(ll x)
  46. {
  47. if(x<0)
  48. x=-x,putchar('-');
  49. if(x>=10)
  50. put(x/10);
  51. putchar(x%10+'0');
  52. }
  53. inline ll qp(ll x,ll p,ll mod)
  54. {
  55. ll ans=1;
  56. while(p)
  57. {
  58. if(p&1)
  59. ans=(ans*x)%mod;
  60. x=(x*x)%mod,p>>=1;
  61. }
  62. return ans;
  63. }
  64. ll MF(ll n,ll p,ll pc)//compute n! by pc norm
  65. {
  66. if(n==0)
  67. return 1;
  68. ll res=1;
  69. for(rg ll i=2;i<=pc;++i)
  70. if(i%p)//don't compute the p factor for it has been computed out of the function.
  71. res=(res*i)%pc;//compute the single recurring period
  72. res=qp(res,n/pc,pc);//compute the all recurring period
  73. for(rg ll i=2;i<=n%pc;++i)//compute the res num. out of recper.
  74. if(i%p)
  75. res=(res*i)%pc;
  76. return res*MF(n/p,p,pc)%pc;
  77. }
  78. inline ll inver(ll n,ll mod)
  79. {
  80. ll x,y;
  81. exgcd(n,mod,x,y);
  82. return (x+=mod)>mod?x-mod:x;
  83. }
  84. inline ll C(ll n,ll m,ll p,ll pc)
  85. {
  86. 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
  87. ll d=0;
  88. for(rg ll i=n;i>0;i/=p)
  89. d+=i/p;//d(n!)
  90. for(rg ll i=m;i>0;i/=p)
  91. d-=i/p;//d(m!)
  92. for(rg ll i=n-m;i>0;i/=p)
  93. d-=i/p;//d((n-m)!)
  94. //k=d(n!)-d(m!)-d((n-m)!)
  95. //d(n) is the fac p's num in n
  96. return fc_n*qp(p,d,pc)%pc*inver(fc_m,pc)%pc*inver(fc_del,pc)%pc;
  97. }
  98. inline ll CRT(ll b,ll mod)
  99. {
  100. return b*inver(P/mod,mod)%P*(P/mod)%P;
  101. }//add ans:aiMiti
  102. /*
  103. suppose P=\prod(p_i^{c_i})
  104. the origin equation x=C(n,m)(mod P) is equivalance to:
  105. {x=C(n,m)(mod p_i^{c_i})} for each factor is perpendicular
  106. then we can solve the subans in turn and combine them.
  107. ans=\sum_{i=1}^{n}{a_i M_i t_i}
  108. M_i = P/(p_i^{c_i})
  109. t_i is the inversion of M_i by p_i^{c_i} norm
  110. */
  111. inline ll exlucas(ll n,ll m)//main function
  112. {
  113. ll res=0,cur=P,pc;
  114. ll Sqr=sqrt(P)+5;
  115. for(rg ll i=2;i<=Sqr;++i) //limit the searching range:sqrt(n) technique
  116. {
  117. if(cur%i==0)// i|cur
  118. {
  119. pc=1;
  120. while(cur%i==0)
  121. pc*=i,cur/=i;//p_i=i,p_i^{c_i}=pc
  122. res=(res+CRT(C(n,m,i,pc),pc))%P;
  123. }
  124. }
  125. if(cur>1)//cur=sqrt(P)
  126. res=(res+CRT(C(n,m,cur,cur),cur))%P;
  127. return res;
  128. }
  129. int main()
  130. {
  131. //fre("P4720");
  132. n=qr(1ll),m=qr(1ll),P=qr(1ll);
  133. put(exlucas(n,m));
  134. return 0;
  135. }

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. ssl安全验证

    #ssl验证 r=requests.get('https://www.12306.cn',verify=False) print(r.content.decode('utf-8')) 结果:

  2. Python学习【day04】- Python基础(集合、函数)

    集合 #!/usr/bin/env python # -*- coding:utf8 -*- # set集合 只可放不可变的数据类型,本身是可变数据类型,无序 # s = {1,2,3,[1,2,3] ...

  3. Eclipse中导入Maven Web项目并配置其在Tomcat中运行

    今天因为实习的关系需要讲公司已经开发的项目导入进Eclipse,而公司的项目是用Maven来构建的所以,需要将Maven项目导入进Eclipse下. 自己因为没有什么经验所以搞了得两个多小时,在这里和 ...

  4. vs2019编译opencv

    序 微软家的宇宙第一ide:visual studio已经更新到了2019版,芒果也更新尝鲜了一遍,体验还不错,建议更新尝尝鲜.芒果顺便使用vs2019编译了一遍opencv,编译过程也非常顺利,以下 ...

  5. git删除已经push的远程文件或文件夹

    在使用git提交项目时,有时候会误提交一下文件,比如:*.iml,*.project,*.settings,.idea/*等文件,有时候这些不需要提交的文件可以加入到.gitignore,在提交的时候 ...

  6. Css常用的技巧

    一.使用css缩写 使用缩写可以帮助减少你CSS文件的大小,更加容易阅读.  具体内容请浏览:CSS常用缩写语法 二.明确定义单位,除非值为0. 忘记定义尺寸的单位是CSS新手普遍的错误.在HTML中 ...

  7. centos配置mutt和msmtp发送邮件

    一.安装mutt yum install mutt -y 二.配置mutt vim /etc/Muttrc 在里面找到下面几行,并将内容修改为你自己的内容(下面几行分布在不同位置,请耐心查找,记得去掉 ...

  8. Altium Designer 编译原理图出现has no driving source警告解决办法

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明. 作者:struct_mooc 博客地址:https://www.cnblogs.com/stru ...

  9. vue路由守卫触发顺序

    不同组件之间的路由跳转流程图 导航被触发(A–>B) 调用A组件内路由守卫beforeRouteLeave(to,from,next) 调用全局路由前置守卫router.beforeEach(t ...

  10. vue-复制功能插件-兼容性最好的插件

    记录给自己用,不进同一次坑: https://github.com/Inndy/vue-clipboard2