扩展Lucas定理 扩展Lucas板子

题意概述:多组询问,给出N,K,M,要求回答C(N,K)%M,1<=N<=10^18,1<=K<=N,2<=M<=10^6

 

分析:

  模数不为质数只能用扩展Lucas,裸题没什么好说的。

  emmmmmm......知识点我就不讲了吧......(主要是我现在都还没有参透博客园怎么放公式)直接丢代码!加上了一些棒棒的优化~

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #include<set>
 9 #include<map>
10 #include<vector>
11 #include<cctype>
12 using namespace std;
13 typedef long long LL;
14 const int maxn=1000005;
15 
16 LL N,K; int M;
17 int pri[maxn],tot; bool ntp[maxn];
18 
19 void get_pri(){
20     ntp[0]=ntp[1]=1;
21     for(int i=2;i<=1000000;i++){
22         if(!ntp[i]) pri[++tot]=i;
23         for(int j=1;j<=tot&&1ll*pri[j]*i<=1000000;j++){
24             ntp[pri[j]*i]=1;
25             if(i%pri[j]==0) break;
26         }
27     }
28 }
29 void exgcd(int a,int b,LL &d,LL &x,LL &y){
30     if(!b) d=a,x=1,y=0;
31     else exgcd(b,a%b,d,y,x),y-=a/b*x;
32 }
33 int inv(int a,int p){
34     LL d,x,y; exgcd(a,p,d,x,y);
35     return (x%p+p)%p;
36 }
37 int qkpow(int x,LL y,int p){
38     int re=1,t=x;
39     for(int i=0;(1ll<<i)<=y;i++){
40         if((1ll<<i)&y) re=1ll*re*t%p;
41         t=1ll*t*t%p;
42     }
43     return re;
44 }
45 int J(LL n,int p,int pt,int mul){
46     if(n<=1) return 1;
47     int re=1;
48     if(n>=pt) re=qkpow(mul,n/pt,pt);
49     for(int i=1;i<=n%pt;i++)
50         if(i%p) re=1ll*re*i%pt;
51     return 1ll*re*J(n/p,p,pt,mul)%pt;
52 }
53 int C(LL n,LL m,int p,int pt){
54     LL k=0,t;
55     for(t=n;t;t/=p) k+=t/p;
56     for(t=m;t;t/=p) k-=t/p;
57     for(t=n-m;t;t/=p) k-=t/p;
58     int pw=qkpow(p,k,pt); if(!pw) return 0;
59     int mul=1;
60     for(int i=1;i<pt;i++)
61         if(i%p) mul=1ll*mul*i%pt;
62     int a=J(n,p,pt,mul),b=inv(J(m,p,pt,mul),pt),c=inv(J(n-m,p,pt,mul),pt);
63     return 1ll*pw*a%pt*b%pt*c%pt;
64 }
65 int exLucas(LL n,LL m,int p){
66     int re=0,t=p;
67     for(int i=1;i<=tot&&pri[i]<=t;i++){
68         if(t%pri[i]) continue;
69         int pt=1,c;
70         while(t%pri[i]==0) pt*=pri[i],t/=pri[i];
71         c=C(n,m,pri[i],pt);
72         re=(re+1ll*p/pt*c%p*inv(p/pt,pt)%p)%p;
73     }
74     return re;
75 }
76 int main()
77 {
78     get_pri();
79     while(cin>>N>>K>>M) cout<<exLucas(N,K,M)<<'\n';
80     return 0;
81 }
View Code

 

posted @ 2018-04-12 18:43  KKKorange  阅读(356)  评论(0编辑  收藏  举报