组合数
①当参数范围较小的时候,并且有取模,可以直接通过递推式$C_{a}^{b}=C_{a - 1}^{b}+C_{a-1}^{b-1}$直接递推出来。(递推)

1 void init() 2 { 3 for(int i = 0 ; i < N ; i ++) 4 for(int j = 0 ; j <= i ; j ++) 5 if(!j)c[i][j] = 1; 6 else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; 7 }
②当参数范围较小,并且有取模,取模的是一个质数时,可以分别递推分子的阶乘和分母阶乘,分母用逆元递推。其中qmi为快速幂函数。(预处理)

1 fact[0] = infact[0] = 1; 2 for(int i = 1 ; i < N ; i ++) 3 { 4 fact[i] = (LL)fact[i - 1] * i % mod; 5 infact[i] = (LL)infact[i - 1] * qmi(i, mod - 2, mod) % mod; 6 }
③当参数范围变大时,并且有取模,可以使用Lucas定理求解组合数。(定理)
$C_{a}^{b}\equiv C_{a\;mod\;p}^{b\;mod\;p}\cdot C_{a/p}^{b/p}$

1 int C(int a, int b) 2 { 3 int res = 1; 4 for(int i = 1, j = a ; i <= b ; i ++, j --) 5 { 6 res = (LL)res * j % p; 7 res = (LL)res * qmi(i, p - 2) % p; 8 } 9 return res; 10 } 11 12 int lucas(LL a, LL b) 13 { 14 if(a < p && b < p)return C(a, b); 15 else return (LL)C(a % p, b % p) * lucas(a / p, b / p) % p; 16 } 17 18 int main(){ 19 int n; 20 cin >> n; 21 while(n --) 22 { 23 LL a, b; 24 cin >> a >> b >> p; 25 cout << lucas(a, b) << endl; 26 } 27 return 0; 28 }
④当要求求组合数的确切值,并没有取模时,需要分解阶乘和质因数,最后用高精度相乘求出结果。(分解质因数)
![]()
1 int get(int n, int p)//获取阶乘中某个质因子的个数 2 { 3 int res = 0; 4 while(n) 5 { 6 res += n / p; 7 n /= p; 8 } 9 return res; 10 } 11 12 void get_primes(int n) 13 { 14 for(int i = 2 ; i <= n ; i ++) 15 { 16 if(!st[i])primes[cnt ++] = i; 17 for(int j = 0 ; i * primes[j] <= n ; j ++) 18 { 19 st[i * primes[j]] = true; 20 if(i % primes[j] == 0)break; 21 } 22 } 23 } 24 25 vector<int> mul(vector<int> a, int b)//高精度乘 26 { 27 vector<int> c; 28 int t = 0; 29 for(int i = 0 ; i < a.size() ; i ++) 30 { 31 t += a[i] * b; 32 c.push_back(t % 10); 33 t /= 10; 34 } 35 36 while(t) 37 { 38 c.push_back(t % 10); 39 t /= 10; 40 } 41 return c; 42 } 43 44 int main(){ 45 cin >> a >> b; 46 47 get_primes(a); 48 49 for(int i = 0 ; i < cnt ; i ++) 50 { 51 int p = primes[i]; 52 sum[i] = get(a, p) - get(b, p) - get(a - b, p);//sum存储每个质因子的个数 53 } 54 55 vector<int> res; 56 res.push_back(1); 57 for(int i = 0 ; i < cnt ; i ++) 58 for(int j = 0 ; j < sum[i] ; j ++) 59 res = mul(res, primes[i]); 60 61 62 63 for(int i = res.size() - 1 ; i >= 0 ; i --)cout << res[i]; 64 puts(" "); 65 return 0; 66 67 }

浙公网安备 33010602011771号