数学知识:求组合数(二)

简介: 复习acwing算法基础课的内容,本篇为讲解数学知识:求组合数,关于时间复杂度:目前博主不太会计算,先鸽了,日后一定补上。

AcWing 887. 求组合数 III

本题链接:AcWing 887. 求组合数 III

本博客提供本题截图:

image.png

本题解析

卢卡斯定理:

image.png

我们知道直接进行除法的话会有精度问题,所以我们可以用逆元去求解,关于逆元的求法见数学知识:快速幂

AC代码

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
int qmi(int a, int k, int p)
{
    int res = 1;
    while (k)
    {
        if (k & 1) res = (LL)res * a % p;
        a = (LL)a * a % p;
        k >>= 1;
    }
    return res;
}
int C(int a, int b, int p)
{
    if (b > a) return 0;
    int res = 1;
    for (int i = 1, j = a; i <= b; i ++, j -- )
    {
        res = (LL)res * j % p;
        res = (LL)res * qmi(i, p - 2, p) % p;
    }
    return res;
}
int lucas(LL a, LL b, int p)
{
    if (a < p && b < p) return C(a, b, p);
    return (LL)C(a % p, b % p, p) * lucas(a / p, b / p, p) % p;
}
int main()
{
    int n;
    cin >> n;
    while (n -- )
    {
        LL a, b;
        int p;
        cin >> a >> b >> p;
        cout << lucas(a, b, p) << endl;
    }
    return 0;
}

AcWing 888. 求组合数 IV

本题链接:AcWing 888. 求组合数 IV

本博客提供本题截图:

image.png

本题解析

这个题就是直接硬算,利用公式直接展开进行计算,注意本题需要用到高精度乘法,高精度乘法的模板见:高精度运算,展开方式如下图:

image.png

展开的过程中注意化简:我们把分母和分子使用分解质因数的形式进行化简,分解质因数见:数学知识:质数

AC代码

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 5010;
int primes[N], cnt;
int sum[N];
bool st[N];
void get_primes(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)
{
    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;
    cin >> a >> b;
    get_primes(a);
    for (int i = 0; i < cnt; i ++ )
    {
        int p = primes[i];
        sum[i] = get(a, p) - get(a - b, p) - get(b, p);
    }
    vector<int> res;
    res.push_back(1);
    for (int i = 0; i < cnt; i ++ )
        for (int j = 0; j < sum[i]; j ++ )
            res = mul(res, primes[i]);
    for (int i = res.size() - 1; i >= 0; i -- ) printf("%d", res[i]);
    puts("");
    return 0;
}


目录
相关文章
|
10月前
|
算法 测试技术 C++
【动态规划】【状态压缩】【C++算法】1815 得到新鲜甜甜圈的最多组数
【动态规划】【状态压缩】【C++算法】1815 得到新鲜甜甜圈的最多组数
|
9月前
线性代数——(期末突击)行列式(下)-行列式按行展开、范德蒙行列式、克拉默法则
线性代数——(期末突击)行列式(下)-行列式按行展开、范德蒙行列式、克拉默法则
296 7
|
算法 C++
C++基础算法二分篇
C++基础算法二分篇
|
容器
数学|泊松分酒问题蕴藏的数学知识
数学|泊松分酒问题蕴藏的数学知识
242 0
|
存储 算法 vr&ar
算法步步为营(02)-两数之和
两个非空链表,表示两个非负整数。它们每位数字都是逆序存储,且每个节点只能存储一位数字。 将两个数相加,并以相同形式返回一个表示和的链表。除了数字 0 之外,这两个数都不会以 0 开头。
115 0
|
机器学习/深度学习 算法 索引
算法步步为营(1)-两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。可以按任意顺序返回答案。
101 0
【数理统计】一题了解假设检验
【数理统计】一题了解假设检验
416 0
【数理统计】一题了解假设检验
|
算法
数学知识:求组合数(一)
复习acwing算法基础课的内容,本篇为讲解数学知识:求组合数,关于时间复杂度:目前博主不太会计算,先鸽了,日后一定补上。
166 0
数学知识:求组合数(一)
|
算法
数学知识:求组合数(三)
复习acwing算法基础课的内容,本篇为讲解数学知识:求组合数,关于时间复杂度:目前博主不太会计算,先鸽了,日后一定补上。
147 0
数学知识:求组合数(三)
|
Java BI
二分快速幂-题型归纳与总结
二分快速幂-题型归纳与总结
117 0
二分快速幂-题型归纳与总结