用途:
当C(a,b)较大,p较小时,求C(a,b)%p,上界为plogpa
定理:
(证明略)
处理过程就和就p进制数相似,%p,/p,知道a,b中一个为0。
对于C(mi,ni)%p,求解过程如下:
C(mi,ni)=mi!/ni!/(m-n)!,设C(mi,ni)%p=x
mi!/(m-n)i!=x*n!(mod p)
mk=mi!/(m-n)i!%p(这个是可以算的) nk=ni!%p(这也可以)
mk=x*nk(mod p)
因为gcd(nk,p)=1,所以nk有逆元,两边同乘逆元 逆元求法
x=mk*(nk)^(-1)(mod p) (此处^-1为逆元)
就求出来了。
代码:
#include<iostream> #include<vector> #include<queue> #include<cstring> #include<algorithm> #include<cmath> #include<cstdio> #include<map> #define MAX(a,b) (a)>(b)?(a):(b) #define MIN(a,b) (a)<(b)?(a):(b) #define INF 0x7f7f7f7f #define MAX_INT 0x7fffffff #define pi 3.1415926 typedef long long LL; typedef unsigned int uint; using namespace std; LL inv(LL a,LL p){//a^(p-2) LL n=p-2,ans=1; while(n){ if(n&1){ ans=ans*a%p; } a=a*a%p; n>>=1; } return ans; } LL C(LL a,LL b,LL p){ if(b>a)return 0; if(b==a)return 1; LL ai=1,bi=1; if(b>b-a)b=b-a; for(int i=0;i<b;i++){ ai=ai*(a-i)%p; bi=bi*(b-i)%p; } return ai*inv(bi,p)%p; } LL lucas(LL a,LL b,LL p){ LL ans=1; while(a&&b){ ans=(ans*C(a%p,b%p,p))%p; a/=p; b/=p; } return ans; } int main(){ int t; cin>>t; LL n,m,p; while(t--){ cin>>n>>m>>p; cout<<lucas(n,m,p)<<endl; } return 0; }