首页 > 其他分享 >求组合数专题

求组合数专题

时间:2024-09-30 22:52:34浏览次数:10  
标签:专题 组合 int ll base expo retv mod

求组合数 Ⅰ(递推公式)

思路 O(a\cdot b)

  • 递推法预处理
    • 利用公式 C_{a}^{b} = C_{a-1}^{b-1} + C_{a-1}^{b}
    • 复杂度 O(a \cdot b) = 4*10^{6}
  • 直接查询
    • 单次查询复杂度 O(1)

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 2010;
const int mod = 1e9+7;
int c[N][N];
int get_c(int a, int b)
{
    c[0][0] = 1;
    for(int i = 1; i <= a; i++)
    {
        c[i][0] = 1;
        for(int j = 1; j <= a; j++)
        {
            c[i][j] = (c[i-1][j-1] + c[i-1][j]) % mod;
        }
    }
    
    return c[a][b];
}
int main()
{
    get_c(2000, 2000);
    
    int n;
    cin >> n;
    while (n -- ){
        int a, b;
        cin >> a >> b;
        cout << c[a][b] << '\n';
    }
}

求组合数 Ⅱ (乘法逆元、费马小定理、快速幂)

思路 O(1e5 \cdot log(p-2) + n)

  • 很明显,递推法预处理会超时。于是我们选择另一种计算组合数的方式:快速幂(处理分子的阶乘、分母的阶乘) + 费马小定理(将除以分母,在模运算中该换为,乘以分母的乘法逆元)
    • 步骤       
      • 计算阶乘 O(b_{max}) = 10^{5}
      • 快速幂求乘法逆元 O(log(p-2)) ,p = 1e9+7
    • 总复杂度 O(n \cdot (b_{max} + log(p-2))) > 10^{9}
    • 反思:不同的数据计算阶乘时重复计算了
    • 改进:预处理所有阶乘 1e5
      • (同时可以预处理所有阶乘的乘法逆元)O(1e5 * log(p-2))
    • 注意:求 \frac{a!}{(a-b)!} 时 仍不能用除法,要采用乘法逆元

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const int mod = 1e9+7;
typedef long long ll;
ll fac[N], ifac[N];
ll qmi(ll base, ll expo)
{
    ll retv = 1;
    while(expo)
    {
        if(expo & 1) retv = retv * base % mod;
        base = base * base % mod;
        expo >>= 1;
    }
    
    return retv;
}
void init()
{
    fac[0] = ifac[0] = 1;
    for(ll i = 1; i <= 100000; i++)
    {
        fac[i] = fac[i-1] * i % mod;
        ifac[i] = qmi(i, mod-2) * ifac[i-1] % mod;
    }
}
int main()
{
    init();
    
    int n;
    cin >> n;
    while (n -- ){
        int a, b;
        cin >> a >> b;
        
        cout << fac[a] * ifac[a-b] % mod * ifac[b] % mod << '\n';
    }
}

求组合数 Ⅲ(卢卡斯定理)

思路 

  • 无它,ab值太大了,幸好最后是mod运算,用卢卡斯定理即可 C_{a}^{b} = C_{a \mod p}^{b \mod p} \cdot C_{\frac{a}{p}}^{\frac{b}{p}}
    • 条件: p是质数

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
typedef long long ll;
ll qmi(ll base, ll expo, ll mod)
{
    ll retv = 1;
    while(expo)
    {
        if(expo & 1) retv = retv * base % mod;
        base = base * base % mod;
        expo >>= 1;
    }
    
    return retv;
}
ll get_c(ll a, ll b, ll mod)
{
    
    ll res = 1;
    for(int i = 1, j = a; i <= b; i++, j--)
    {
        res = res * j % mod;
        res = res * qmi(i, mod-2, mod) % mod;
    }
    
    return res;
}
ll lucas(ll a, ll b, ll mod)
{
    if(a < mod && b < mod)return get_c(a,b,mod);
    else return get_c(a % mod, b % mod, mod) * lucas(a / mod, b / mod, mod) % mod;
}
int main()
{
    int n;
    cin >> n;
    while (n -- ){
        ll a, b, p;
        cin >> a >> b >> p;
        
        cout << lucas(a, b, p) << '\n';
    }
    
    return 0;
}

求组合数 Ⅳ(高精度乘法、质因数分解)

思路

  • 阶乘的质因数分解 + 高精度乘法
#include <bits/stdc++.h>
using namespace std;
const int N = 5010;
int primes[N], cnt;
bool st[N];
int s[N];
vector<int> v;
void get_primes(int n)
{
    for(int i = 2; i <= n; i++)
    {
        if(!st[i]) primes[++cnt] = i;
        for(int j = 1; primes[j] * i <= n; j++)
        {
            st[primes[j] * i] = true;
            if(i % primes[j] == 0) break;
        }
    }
}
int cal(int x, int p)
{
    int retv = 0;

    while(x)
    {
        retv += x/p;
        x /= p;
    }
    
    return retv;
}

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()
{
    get_primes(5000);
    
    int a, b;
    cin >> a >> b;
    
    v.push_back(1);
    for(int i = 1; i <= cnt; i++)
    {
        int p = primes[i];
        s[p] = cal(a, p) - cal(a-b, p) - cal(b, p);
        for(int j = 1; j <= s[p]; j++)
            v = mul(v, p);
    }
    
    for(int i = v.size()-1; i >= 0; i--) 
        cout << v[i];
        
    return 0;
}

标签:专题,组合,int,ll,base,expo,retv,mod
From: https://blog.csdn.net/m0_73669127/article/details/142655175

相关文章

  • 二叉树深搜专题篇
    目录计算布尔二叉树的值求根节点到叶节点数字之和二叉树剪枝验证二叉搜索树二叉搜索树中第K小的元素二叉树的所有路径计算布尔二叉树的值题目思路这道题其实是比较简单的,对二叉树来一次后序遍历即可,当遇到叶子结点直接返回叶子节点中的bool值即可,否则继续进行后......
  • 在面向对象编程中,感觉桥接和组合好像很像,他们有什么共性和差别呢
    1.相关链接最简单的桥接模式-CSDN博客最简单的理解组合模式_组合模式举例-CSDN博客 2.内容在面向对象编程中,桥接模式和组合模式确实有一些相似之处,但它们在设计理念和应用场景上存在显著的差异。以下是对这两种模式的共性和差别的详细分析:共性结构型设计模式:桥接模式和......
  • CMSIS-RTOS V2封装层专题视频,一期视频将常用配置和用法梳理清楚,适用于RTX5和FreeRTOS(2
    【前言】本期视频就一个任务,通过ARM官方的CMSISRTOS文档,将常用配置和用法给大家梳理清楚。对于初次使用CMSIS-RTOS的用户来说,通过梳理官方文档,可以系统的了解各种用法,方便大家再进一步的自学或者应用,起到授人以渔的作用。更深入的可以看之前分享的RTOS运行机制,任务管理,上下......
  • 【专题】新能源发电行业及其市场化进程概览白皮书报告合集PDF分享(附原数据表)
    原文链接:https://tecdat.cn/?p=37802随着中国经济结构的持续优化以及能源政策的不断进步,我国的能源消费呈现出稳定增长的态势。与此同时,能源利用效率逐步提高,清洁能源在能源结构中的比例也在稳步上升,这为国家的可持续发展战略提供了有力的支撑。文末204份电力行业研究报告最新趋......
  • (40)时钟专题--->(040)IBUF + BUFG
    1.1.1本节目录1)本节目录2)本节引言3)FPGA简介4)IBUF+BUFG5)结束语1.1.2本节引言“不积跬步,无以至千里;不积小流,无以成江海。就是说:不积累一步半步的行程,就没有办法达到千里之远;不积累细小的流水,就没有办法汇成江河大海。1.1.3FPGA简介FPGA(FieldProgrammableGateArr......
  • 2024-2025专题二题单 - 题解
    A-MoneyinHand(记忆化搜索)原题链接题解B-GoodGraph(并查集)原题链接题解C-IceSkating(dfs求连通块)原题链接题解D-TheLakes(dfs求连通块,连通块内累加,多组数据注意初始化)原题链接题解E-LearningLanguages(建图,dfs统计连通块个数,答案为个数-1)原题链接题......
  • [大语言模型-论文精读] Diffusion Model技术-通过时间和空间组合扩散模型生成复杂的3D
    ​​​​​​GenerationofComplex3DHumanMotionbyTemporalandSpatialCompositionofDiffusionModelsLMandelli,SBerretti -arXivpreprintarXiv:2409.11920,2024通过时间和空间组合扩散模型生成复杂的3D人物动作摘要本文提出了一种新的方法,用于生成在......
  • 网络专题
    1.你工作中了解哪些缓存技术?最少三种RedisCDN浏览器缓存Linux的buffer(缓冲)和cache(缓存)2.你用过哪些抓包技术?最少两种?wiresharktcpdump3.tcpdump如何抓取eth0接口的icmp报文?tcpdump是一个强大的网络包分析工具,用于捕获和显示经过网络接口的网络数据包。它常用于故障排......
  • 2024-2025专题一题单 - 题解
    A-Virus原题链接题解B-Coverage原题链接题解C-Sensors原题链接题解D-MakeTakahashiHappy原题链接题解E-Don’tbecycle原题链接题解F-AlmostEqual原题链接题解G-StepUpRobot原题链接题解H-SnukeMaze原题链接题解I-MEX原题链接......
  • 设计模式之组合模式
    组合模式组合模式是一种结构型设计模式,用于将对象组织成树形结构以表示部分-整体的层次关系。它使得客户端可以统一地处理单个对象和组合对象。核心概念透明性:组合模式通过使组件的接口包含管理子部件的操作(如添加、删除等),提供了透明的操作方式。这意味着客户端无需关心它正......