AcWing 888. 分解质因数法求组合数(模板)

题目链接:点击这里

在这里插入图片描述
思路:将组合数分解质因数 p 1 c 1 p 2 c 2 . . . p k c k p_1^{c_1}p_2^{c_2}...p_k^{c_k} ,再利用高精度乘法即可求解。

C n m = n ! m ! ( n m ) ! C_n^m=\frac{n!}{m!(n-m)!}

如何求 n ! n! 中有多少个因子 p p ?

n p + n p 2 + n p 3 + . . . \lfloor \frac{n}{p} \rfloor+\lfloor \frac{n}{p^2} \rfloor+\lfloor \frac{n}{p^3} \rfloor+...

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>

using namespace std;

const int N = 5010;

int primes[N], cnt;
bool st[N];
int sum[N];

void get_prime(int n)       //线性筛
{
    for(int i = 2; i <= n; ++i)
    {
        if(!st[i])  primes[cnt++] = i;
        for(int j = 0; primes[j] <= n / i; ++j)
        {
            st[primes[j] * i] = true;
            if(i % primes[j] == 0)  break;
        }
    }
}

int get(int n, int p)   //求n!中有多少个因子p
{
    int res = 0;
    while(n)
    {
        res += n / p;
        n /= p;
    }
    return res;
}

vector<int> mul(vector<int> a, int b)   //高精度乘以低精度
{
    vector<int> c;
    int t = 0;
    for(int i = 0; i < a.size(); ++i)
    {
        t += a[i] * b;
        c.push_back(t % 10);
        t /= 10;
    }
    
    while(t)
    {
        c.push_back(t % 10);
        t /= 10;
    }
    return c;
}

int main()
{
    int a, b;
    scanf("%d%d", &a, &b);
    
    get_prime(a);
    
    // for(int i = 0; i < cnt; ++i)    printf("%d ", primes[i]);
    // puts("");
    
    for(int i = 0 ; i < cnt; ++i)
    {
        int p = primes[i];
        sum[i] = get(a, p) - get(b, p) - get(a - b, p);
    }
    
    // for(int i = 0; i < cnt; ++i)    printf("%d ", sum[i]);
    // puts("");
    
    vector<int> ans;
    ans.push_back(1);
    
    for(int i = 0; i < cnt; ++i)
        for(int j = 0; j < sum[i]; ++j)
            ans = mul(ans, primes[i]);
    
    for(int i = ans.size() - 1; i >= 0; --i)    printf("%d", ans[i]);
    puts("");
    
    return 0;
}
发布了811 篇原创文章 · 获赞 127 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/104815088