博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lucas卢卡斯定理
阅读量:6890 次
发布时间:2019-06-27

本文共 2329 字,大约阅读时间需要 7 分钟。

  当$p$为素数时

  $$C_n^m\equiv C_{n/p}^{m/p}*C_{n\%p}^{m\%p}(mod\ p)$$

  设$n=s*p+q,m\equiv t*p+r(q,r<=p)$

  我们要证$C_{s*p+q}^{t*p+r}\equiv C_s^t*C_q^r$

  首先得有个前置知识,费马小定理$x^p\equiv x(mod\ p)$

  那么$(x+1)^p\equiv x+1(mod\ p)$

  且$x^p+1\equiv x+1(mod\ p)$

  所以$(x+1)^p\equiv x^p+1$

  然后$(x+1)^n\equiv (x+1)^{s*p+q}$

  $\equiv ((x+1)^p)^s*(x+1)^q$

  $\equiv (x^p+1)^s*(x+1)^q$

  然后用二项式定理展开

  $\equiv \sum _{i=0}^s C_s^i*x^{i*p}*\sum_{j=0}^qC_q^j*x^j$

  总之就是$(x+1)^p\equiv \sum _{i=0}^s C_s^i*x^{i*p}*\sum_{j=0}^qC_q^j*x^j$

  然后考虑把两边的多项式展开一下

  那么两边肯定都有$x^m$即$x^{t*p+r}$这一项(这是最上面的假设)

  左边的$x^m$的系数,根据上面的性质4推出来,应该是$C_n^m$

  然后右边嘞?只有$i=t,j=r$的时候才会有这一项,所以这一项的系数就是$C_s^t*C_q^r$

  然后又因为$s=n/p,t=n\%p,q=m/p,r=m\%p$

  然后就能证明$C_n^m\equiv C_{n/p}^{m/p}*C_{n\%p}^{m\%p}(mod\ p)$

  然而万一$q<r$该怎么办?那样的话$j$根本不可能等于$r$啊?

  所以那样的话答案就是$0$

  因为上面乘上$C_{n\%p}^{m\%p}$答案就是$0$

  如何证明?

  我们设$f=n-m=z*p+x$

  因为$r>t,x+r\equiv t(mod\ p)$

  所以$x+r=p+t$

  又因为$z*p+x+q*p+r=s*p+t$

  所以$z+q=s-1$

  那么带进通项公式$C_n^m=\frac {n!}{m!*f!}$之后,分子中有$s$个$p$的倍数(不考虑有$p^2$之类的,因为下面有的话上面肯定也有),分母中有$s-1$个$p$的倍数,抵消之后分子中还有一个$p$,那么这个数就是$p$的倍数,模$p$肯定余$0$啦

  累死我了……

1 // luogu-judger-enable-o2 2 //minamoto 3 #include
4 #include
5 #define ll long long 6 using namespace std; 7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 8 char buf[1<<21],*p1=buf,*p2=buf; 9 inline ll read(){10 #define num ch-'0'11 char ch;bool flag=0;ll res;12 while(!isdigit(ch=getc()))13 (ch=='-')&&(flag=true);14 for(res=num;isdigit(ch=getc());res=res*10+num);15 (flag)&&(res=-res);16 #undef num17 return res;18 }19 const int N=100005;20 ll n,m,p;21 ll fac[N],inv[N];22 void init(){23 fac[0]=1;24 for(int i=1;i<=p;++i)25 fac[i]=fac[i-1]*i%p;26 }27 ll qpow(ll a,ll b){28 ll res=1;29 while(b){30 if(b&1) res=res*a%p;31 b>>=1,a=a*a%p;32 }33 return res;34 }35 ll C(ll n,ll m){36 if(m>n) return 0;37 return fac[n]*qpow(fac[m]*fac[n-m],p-2)%p;38 }39 ll Lucas(ll n,ll m){40 if(m==0) return 1;41 return Lucas(n/p,m/p)*C(n%p,m%p)%p;42 }43 int main(){44 int T=read();45 while(T--){46 n=read(),m=read(),p=read();47 init();48 printf("%lld\n",Lucas(m+n,m));49 }50 return 0;51 }

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9522728.html

你可能感兴趣的文章
C语言结构体指针成员强制类型转换
查看>>
软件工程第二章 习题2 第4题
查看>>
《JavaScript设计模式与开发实践》读书笔记之命令模式
查看>>
hdu Problem 1242 Rescue bfs + 优先队列
查看>>
HDU-1507-Uncle Tom's Inherited Land*
查看>>
force里面的射线检测
查看>>
oracle 12.1.0.2中对象锁对系统的较大影响
查看>>
tensorboard的使用
查看>>
java进程占用CPU资源过高分析脚本
查看>>
day17--JQuery实例
查看>>
网络对抗技术作业一
查看>>
最短路(Floyd_Warshall) POJ 2240 Arbitrage
查看>>
spring boot 配置mybatis plus 控制台打印sql
查看>>
Windows系统安装Apache-tomacat
查看>>
补习系列(11)-springboot 文件上传原理
查看>>
《用正确的方法解决问题100%》读书笔记
查看>>
CodeChef March Challenge 2019题解
查看>>
STL容器底层数据结构的实现
查看>>
Web设计的Ruby on Rails 第2章 变量、数组、散列表
查看>>
关于提升自己
查看>>