FOJ 2020 組合(組合數取素數摸模板:Lucas)
阿新 • • 發佈:2019-02-08
Problem 2020 組合
Accept: 776 Submit: 1849
對於每組資料,輸出一個正整數,表示C(n,m) mod p的結果。
Accept: 776 Submit: 1849
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
給出組合數C(n,m), 表示從n個元素中選出m個元素的方案數。例如C(5,2) = 10, C(4,2) = 6.可是當n,m比較大的時候,C(n,m)很大!於是xiaobo希望你輸出 C(n,m) mod p的值!Input
輸入資料第一行是一個正整數T,表示資料組數 (T <= 100) 接下來是T組資料,每組資料有3個正整數 n, m, p (1 <= m <= n <= 10^9, m <= 10^4, m < p < 10^9, p是素數) Output
對於每組資料,輸出一個正整數,表示C(n,m) mod p的結果。
Sample Input
25 2 35 2 61Sample Output
110Source
FOJ有獎月賽-2011年04月(校賽熱身賽) AC code:#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #include<map> #include<stack> #include<vector> #define LL long long #define MAXN 1000010 using namespace std; const int N=20;//模方程數 LL a[N],mod[N]; /*LL mul(LL a,LL b,LL mod)//a*b%mod { LL ans=0; while(b){ if(b&1) ans=(ans+a)%mod; b>>=1; a=(a+a)%mod; } return ans; } */ LL quick_mod(LL a,LL b,LL m)//a^b%m { LL ans=1; a%=m; while(b) { if(b&1) { ans=ans*a%m; } b>>=1; a=a*a%m; } return ans; } LL getC(LL n,LL m,int cur)//C(n,m)%mod[cur] { LL p=mod[cur]; if(m>n) return 0; if(m>n-m) m=n-m; LL ans=1; for(int i=1;i<=m;i++) { LL a=(n+i-m)%p; LL b=i%p; //ans=mul(ans,mul(a,quick_mod(b,p-2,p),p),p);//p為素數,i對p的逆元可以不用擴張歐幾里得進行求解 re=i^(P-2) //ans=(ans*(a*quick_mod(b,p-2,p))%p)%p; ans = ans * (a * quick_mod(b, p-2,p) % p) % p; } return ans; } LL Lucas(LL n,LL k,int cur)//求C(n,k)%mod[cur] { LL p=mod[cur]; if(k==0) return 1%p; //return getC(n%p,k%p,cur)*Lucas(n/p,k/p,cur)%p; return getC(n % p, k % p,cur) * Lucas(n / p, k / p,cur) % p; } /*void extend_Euclid(LL a,LL b,LL &x,LL &y) { if(b==0) { x=1; y=0; return; } extend_Euclid(b,a%b,x,y); LL tmp=x; x=y; y=tmp-a/b*y; } LL CRT(LL a[],LL m[],int k)//求C(n,m)%M,其中M=(m0*m2*…*m(k-1)),mi為素數,則先用a[i]儲存模方程C(n,m)%mi, { //m[]儲存所有素數因子mi,k表示總共有k個模方程,返回C(n,m)%M的值 LL M=1; LL ans=0; for(int i=0;i<k;i++) M*=mod[i]; for(int i=0;i<k;i++) { LL x,y,tmp; LL Mi=M/m[i]; extend_Euclid(Mi,m[i],x,y); if(x<0) { x=-x; tmp=mul(Mi,x,M); tmp=mul(tmp,a[i],M); tmp=-tmp; } else { tmp=mul(Mi,x,M); tmp=mul(tmp,a[i],M); } ans=(ans+tmp)%M; } while(ans<0) ans+=M; return ans; }*/ int main() { //freopen("D:\\in.txt","r",stdin); int T; scanf("%d",&T); while(T--) { LL n,m; int k; scanf("%lld%lld",&n,&m); k=1; for(int i=0;i<k;i++) scanf("%lld",&mod[i]); for(int i=0;i<k;i++) a[i]=Lucas(n,m,i)%mod[i]; printf("%I64d\n",a[0]); } return 0; }