# 求组合数

##### 基本公式：

C n m = A n m A m m , C n m = n ! m ! ( n − m ) ! C_n^m = \frac{A_n^m}{A_m^m}, C_n^m = \frac{n!}{m!(n - m)!}

#### 定义法：

C n m = n ! m ! ( n − m ) ! = n ! ∗ i n v [ n ! ] ∗ i n v [ ( n − m ) ! ] % m o d C_n^m = \frac{n!}{m!(n - m)!} = n! * inv[n!] * inv[(n - m)!] \% mod

const ll maxn = 1e6 + 5;
const ll mod = 1e9 + 7;
ll fec[maxn],inv[maxn]；
ll qpow(ll a,ll b){
ll res = 1;
while(b){
if(b & 1)
res = (res * a) % mod;
b >>= 1;
a = (a * a) % mod;
}
return res;
}
ll C(ll n,ll m){//求组合数
if(m == 0 || n == m)return 1;
else return fec[n]*inv[m] % mod * inv[n - m] % mod;
}
int main(){
IO;
fec[0] = 1;
for(int i = 1; i <= 2001; i++)
fec[i] = fec[i - 1] * i % mod;//fec存阶乘
inv[2001] = qpow(fec[2001],mod - 2);
for(int i = 2000; i >= 1; i--)
inv[i] = inv[i + 1] * (i + 1) % mod;//递推求逆元
return 0;
}


#### lucas定理求逆元

lucas定理： C n m ≡ C n % p m % p ∗ C n / p m / p ( m o d    p ) C_n^m \equiv C_{n \% p}^{m \% p}*C_{n / p}^{m / p}(\mod p) 其中P为质数(通常比较小)

ll qpow(ll a,ll b){
ll res = 1;
while(b){
if(b & 1)
res = (res * a) % p;
b >>= 1;
a = (a * a) % p;
}
return res;
}
ll C(ll a,ll b){
ll ans = 1;
for(ll i = 1,j = a; i <= b; i++,j--){
ans = (ans * j) % p;
ans = ans * qpow(i,p - 2) % p;
}
return ans;
}
ll lucas(ll a,ll b){
if(a < p && b < p)return C(a,b);
else return C(a % p,b % p) * lucas(a / p,b / p) % p;
}

04-11
07-22 1140

08-02 7565
11-25 1万+
05-13 1733
05-10 4276
02-14 63
02-10 13