题解:AcWing 888 求组合数 IV

【题目来源】

AcWing:888. 求组合数 IV - AcWing题库

【题目描述】

输入 \(a,b\),求 \(C_a^b\) 的值。

注意结果可能很大,需要使用高精度计算。

【输入】

共一行,包含两个整数 \(a\)\(b\)

【输出】

共一行,输出 \(C_a^b\) 的值。

【输入样例】

5 3

【输出样例】

10

【算法标签】

《AcWing 888 求组合数IV》 #组合数学# #组合计数# #高精度#

【代码详解】

#include <bits/stdc++.h>
using namespace std;

const int N = 5005;  // 质数表大小
int primes[N], cnt;  // primes存储质数,cnt是质数个数
bool st[N];          // 筛法标记数组
int sum[N];          // 存储每个质因子的指数

// 线性筛法求1~n的所有质数
void get_primes(int n)
{
    for (int i = 2; i <= n; i++)
    {
        if (!st[i])  // 如果i是质数
        {
            primes[cnt++] = i;  // 加入质数表
        }
      
        // 用当前已得到的质数筛掉合数
        for (int j = 0; primes[j] <= n / i; j++)
        {
            st[primes[j] * i] = true;  // 标记合数
          
            if (i % primes[j] == 0)  // 如果primes[j]是i的最小质因数
            {
                break;  // 保证每个合数只被最小的质因数筛掉
            }
        }
    }
}

// 计算n!中质因子p的指数(勒让德定理)
int get(int n, int p)
{
    int res = 0;  // 指数结果
  
    // 勒让德公式:n!中质因子p的指数 = ⌊n/p⌋ + ⌊n/p²⌋ + ⌊n/p³⌋ + ...
    while (n)
    {
        res += n / p;  // 计算⌊n/p⌋
        n /= p;        // 继续计算下一项
    }
  
    return res;
}

// 高精度乘法:大整数A乘以小整数b
vector<int> mul(vector<int> &A, int b)
{
    vector<int> C;  // 存储结果
  
    int t = 0;  // 进位
    for (int i = 0; i < A.size() || t; i++)  // 遍历A的每一位或还有进位
    {
        if (i < A.size())  // 如果A还有位数
        {
            t += A[i] * b;  // 当前位乘以b加上进位
        }
        C.push_back(t % 10);  // 取个位
        t /= 10;              // 计算进位
    }
  
    // 去掉前导0,但保留最后一位0(如果结果就是0)
    while (C.size() > 1 && C.back() == 0)
    {
        C.pop_back();
    }
  
    return C;
}

int main()
{
    int a, b;  // 输入C(a, b)
    cin >> a >> b;
  
    // 1. 筛出1~a的所有质数
    get_primes(a);
  
    // 2. 计算组合数C(a,b)的质因数分解
    for (int i = 0; i < cnt; i++)
    {
        int p = primes[i];  // 当前质数
      
        // 勒让德公式计算C(a,b)中质因子p的指数
        // C(a,b) = a! / (b! * (a-b)!)
        // 指数 = 在a!中的指数 - 在b!中的指数 - 在(a-b)!中的指数
        sum[i] = get(a, p) - get(b, p) - get(a - b, p);
    }
  
    // 3. 用高精度乘法计算结果
    vector<int> res;  // 存储高精度结果,低位在前
    res.push_back(1);  // 初始化为1
  
    // 遍历所有质因子
    for (int i = 0; i < cnt; i++)
    {
        int p = primes[i];  // 当前质数
        int exp = sum[i];   // 质因子p的指数
      
        // 将p乘exp次
        for (int j = 0; j < exp; j++)
        {
            res = mul(res, p);
        }
    }
  
    // 4. 输出结果(从高位到低位)
    for (int i = res.size() - 1; i >= 0; i--)
    {
        cout << res[i];
    }
    cout << endl;
  
    return 0;
}

【运行结果】

5 3
10
posted @ 2026-02-24 22:26  团爸讲算法  阅读(1)  评论(0)    收藏  举报