组合数三种求法
1、杨辉三角打表预处理(n,m<=2000)
void Comb(){
for(int i=0;i<N;i++){
c[i][i] = c[i][0] = 1;
for(int j=1;j<i;j++)
c[i][j] = (c[i-1][j] + c[i-1][j-1]) % mod;
}
}
2、预处理阶乘+逆元(n,m<=1e6,mod为质数)
#define mod(x) ((x) % MOD)
typedef long long ll;
ll const MOD = 1e9 + 7;
void pre(){
f[0] = 1;
for(int i=1;i<N;i++) //预处理阶乘
f[i] = mod(f[i-1] * i);
}
ll quick_pow(ll a,ll n){
ll ans = 1;
while(n){
if(n&1) ans = mod(ans * a);
a = mod(a * a);
n >>= 1;
}
return ans;
}
ll comb(ll n,ll m){ //n!/(m!)*(n-m)!
if(n < m) return 0;
return mod(f[n] * quick_pow(mod(f[m]*f[n-m]),MOD-2)); //quikc_pow要加mod
}
3、预处理阶乘逆元(n,m<=1e6,mod为质数)
void pre(){
f[0] = 1;
for(int i=1;i<N;i++) //预处理阶乘
f[i] = mod(f[i-1] * i);
finv[N-1] = quick_pow(f[N-1],MOD-2);
for(int i=N-1;i>0;i--)
finv[i-1] = mod(finv[i] * i); //从后往前处理
}
ll comb(ll n,ll m){
return mod(mod(f[n] * finv[m]) * finv[n-m]);
}