AcWing 888 求组合数 IV
发布日期:2021-05-28 16:27:12 浏览次数:39 分类:精选文章

本文共 1681 字,大约阅读时间需要 5 分钟。

为了计算组合数 ( C(a, b) ),我们需要高精度处理大数运算。以下是详细的解决方案,采用质因数分解和高精度乘法,确保计算结果的准确性。

方法思路

计算组合数 ( C(a, b) = \frac{a!}{b! \cdot (a-b)!} ) 时,直接计算因数会导致大数问题。我们通过以下步骤解决:

  • 质因数筛选

    • 使用线性筛法筛选出所有小于等于 (a) 的质数。
  • 质因数计数

    • 对每个质数 (p),计算 (a!)、(b!) 和 ((a-b)!) 中的质因数 (p) 的次数。
    • 公式为:(C(a, b)) 中 (p) 的次数 (= (\text{次数在 } a!中) - (\text{次数在 } b!中) - (\text{次数在 } (a-b)!中))。
  • 高精度乘法

    • 将分解出的质因数乘到一起,形成最终的组合数。
  • 实现代码

    #include 
    #include
    #include
    using namespace std;const int maxn = 5005;vector
    primes;vector
    sum;void get_primes(int n) { for (int i = 2; i <= n;++) { if (!st[i]) { primes cnt++; primes.push_back(i); } for (int j = 0; primes[j] <= n / i; j++) { st[i * primes[j]] = true; if (i % primes[j] == 0) break; } }}int get(int n, int p) { int res = 0; while (n) { res += n / p; n /= p; } return res;}vector
    mul(vector
    a, int b) { vector
    c; int t = 0; for (int num : a) { t += num * b; c.push_back(t % 10); t /= 10; } while (t) { c.push_back(t % 10); t /= 10; } return c;}int main() { int a, b; cin >> a >> b; get_primes(a); for (int i = 0; i < primes.size(); i++) { int p = primes[i]; sum[i] = get(a, p) - get(b, p) - get(a - b, p); } vector
    res(1, 1); for (int i = 0; i < primes.size(); i++) { for (int j = 0; j < sum[i]; j++) { res = mul(res, primes[i]); } } for (int num : res) { cout << num; }}

    代码解释

  • 质因数筛选:使用线性筛法生成质数列表,确保质数的正确性。
  • 质因数计数:高效计算每个质数在阶乘中的次数,减少重复计算。
  • 高精度乘法:逐位计算,避免处理大数溢出的问题。
  • 该方法确保组合数的计算精确,能够处理较大数值范围,符合题目的要求。

    上一篇:AcWing 889 满足条件的01序列
    下一篇:AcWing 887 求组合数 III

    发表评论

    最新留言

    逛到本站,mark一下
    [***.202.152.39]2025年04月28日 07时55分58秒