yimao哥的求组合数取余的模板,涨姿势了(¯﹃¯)
/* 组合数的计算; C(n,m)= n*(n-1)*...*(n-m+1) / m!; 注意到本题,m最大为10^4,1s的时限(保守估计是10^7),所以直接计算不超时; 分子: fz: 表示分子:fz= n*(n-1)*...*(n-m+1);最多10^4次乘法, 边乘要边取模; 分母: fm: 表示分母:fm= m*(m-1)*...*2*1;最多10^4次乘法, 边乘要边去模; 最后分母要求对模数p的逆元再与分子相乘; */ #include <cstdio> #include <iostream> using namespace std; int ext_gcd(int a, int b, int &x, int &y){ if( !b ) return x=1,y=0,a; int d= ext_gcd(b, a%b, y, x); y-= a/b*x; return d; } int Inv(int a, int m){ int d,x,y; d= ext_gcd(a,m,x,y); return (x%m+m)%m; } /*计算组合数C(n,m)%p,其中m<=10^4,p是素数,且m<p; fm: 表示分母:fm= m*(m-1)*...*2*1; fz: 表示分子:fz= n*(n-1)*...*(n-m+1); 取余对除法不具有封闭性, 必须求出除数(即分母)对模数p的逆元,转换成乘法; C(n,m)= n*(n-1)*...*(n-m+1) / m!; C(n,m)%p = (fz%p) * Inv( (fm%p), p ) %p; */ long long Comb(int n, int m, int p){ long long fm=1, fz= 1; for(int i=2; i<=m; ++i) fm= fm*i%p; for(int i=n-m+1; i<=n; ++i) fz= fz*i%p; long long ret= fz * Inv( fm, p ) %p; return ret<0 ? ret+p : ret; } int main() { //freopen("E.in","r",stdin); int T,n,m,p; cin>>T; while( T-- ){ cin>>n>>m>>p; cout<< Comb( n, m, p ) <<endl; } }