题意概述:多组询问,给出N,K,M,要求回答C(N,K)%M,1<=N<=10^18,1<=K<=N,2<=M<=10^6
分析:
模数不为质数只能用扩展Lucas,裸题没什么好说的。
emmmmmm......知识点我就不讲了吧......(主要是我现在都还没有参透博客园怎么放公式)直接丢代码!加上了一些棒棒的优化~
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include<set> 9 #include 10 #include 11 #include 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<){ 40 if((1ll<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) 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<'\n'; 80 return 0; 81 }
转载于:https://www.cnblogs.com/KKKorange/p/8809725.html