组合数

①当参数范围较小的时候,并且有取模,可以直接通过递推式$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 }

 

posted @ 2020-03-26 16:23  dzcixy  阅读(170)  评论(2)    收藏  举报