Lucas盧卡斯定理

  當$p$爲素數時ios

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

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

  咱們要證$C_{s*p+q}^{t*p+r}\equiv C_s^t*C_q^r$spa

  首先得有個前置知識,費馬小定理$x^p\equiv x(mod\ p)$code

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

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

  因此$(x+1)^p\equiv x^p+1$it

  而後$(x+1)^n\equiv (x+1)^{s*p+q}$io

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

  $\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<iostream>
 4 #include<cstdio>
 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 num
17     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 }
相關文章
相關標籤/搜索