首页 > 其他分享 >组合计数

组合计数

时间:2023-04-29 11:55:57浏览次数:35  
标签:组合 int dfrac 质数 long 计数 res

组合数

\(C^m_n\) = \(\dfrac{n (n-1) (n-2) \cdots (n-m+1)}{m!}\) = \(\dfrac{n!}{m! (n-m)!}\)

\(C^m_n\) = \(C^m_{n-1}\) +\(C^{m-1}_{n-1}\)



递推法求组合数

求组合数Ⅰ \(\quad\) \(C^m_n\) = \(C^m_{n-1}\) +\(C^{m-1}_{n-1}\)

//递推法求组合数模板

//c[a][b]存储C^a_b的方案数
for(int i=0;i<N;i++)
    for(int j=0;j<=i;j++)
        if(j==0)c[i][j]=1;
		else c[i][j]=c[i-1][j]+c[i-1][j-1];



预处理逆元求组合数

首先预处理出所有阶乘取模的余数 fact[N] , 以及所有阶乘取模的逆元 infact[N]

如果取模的数是质数, 可以用费马小定理求逆元


求组合数Ⅱ \(\quad\) \(C^m_n\) = \(\dfrac{n!}{m!(n-m)!}\)

//快速幂模板
int qmi(int a,int k,int p)
{
    int res=1;
    while(k)
    {
        if(k&1)res=(long long)res*a%p;
        a=a*a%p;
        k>>=1;
    }
    return res;
}

//预处理阶乘的余数和阶乘余数的逆元
fact[0]=infact[0]=1;
for(int i=1;i<N;i++)
{
    fact[i]=(long long)fact[i-1]*i%mod;
    infact[i]=(long long)infact[i-1]*qmi(i,mod-2,mod)%mod;
}



Lucas定理

Lucas定理: 若p是质数, 则对于任意整数 1 \(\le\) m \(\le\) n , 有:

\(C^m_n\) \(\equiv\) \(C^{m\%p}_{n\%p}\) \(\cdot\) \(C^{m/p}_{n/p}\) (mod p)


求组合数Ⅲ \(\quad\) \(C^m_n\) \(\equiv\) \(C^{m\%p}_{n\%p}\) \(\cdot\) \(C^{m/p}_{n/p}\) (mod p)

//快速幂模板
int qmi(int a,int k,int p)
{
    int res=1;
    while(k)
    {
        if(k&1)(long long)res=res*a%p;
        a=(long long)a*a%p;
        k>>=1;
    }
    return res;
}

//通过定理求组合数C^a_b
int C(int a,int b,int p)
{
    if(a<b)return 0;
    
    long long x=1,y=1;	//x是分子,y是分母
    for(int i=a,j=1;j<=b;i--,j++)
    {
        x=(long long)x*i%p;
        y=(long long)y*j%p;
    }
    
    return x*(long long)qmi(y,p-2,p)%p;
}

int Lucas(long long a,long long b,int p)
{
    if(a<p&&b<p)return C(a,b,p);
    return (long long)C(a%p,b%p,p)*Lucas(a/p,b/p,p)%p;
}



分解质因数法求组合数

当我们需要求出组合数的真实值, 而非对某个数的余数时, 分解质因数的方式比较好用:

① 筛法求出范围内的所有质数

② 通过 \(C^b_a\) = \(\dfrac{a!}{b!(a-b)!}\) 这个公式求出每个质因子的次数

​ \(\quad\) n ! 中 p 的次数是 [ \(\dfrac{n}{p}\) ] + [ \(\dfrac{n}{p^2}\) ] + \(\cdots\)

③ 用高精度乘法将所有质因子相乘


求组合数Ⅳ

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)	//求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;
}

get_primes(a);	//预处理范围内的所有质数

for(int i=0;i<cnt;i++)	//求每个质因数的次数
{
    int p=primes[i];
    sum[i]=get(a,p)-get(b,p)-get(a-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]);



卡特兰数

给定n个0和n个1, 它们按照某种顺序排成长度为2n的序列, 满足任意前缀中0的个数都不少于1的个数的序列的数量为:

Cat (n) = \(C^n_{2n}\) - \(C^{n-1}_{2n}\) = \(\dfrac{C^n_{2n}}{n+1}\)



标签:组合,int,dfrac,质数,long,计数,res
From: https://www.cnblogs.com/evilboy/p/17363766.html

相关文章

  • 【完全背包的排列问题】NO377. 组合总和 Ⅳ
    [完全背包排列问题]377.组合总和Ⅳ给你一个由不同整数组成的数组nums,和一个目标整数target。请你从nums中找出并返回总和为target的元素组合的个数。题目数据保证答案符合32位整数范围。示例1:输入:nums=[1,2,3],target=4输出:7解释:所有可能的组合为:(1,......
  • 【Jetpack】ViewModel + LiveData + DataBinding 综合使用 ( 核心要点说明 | 组合方式
    文章目录一、ViewModel+LiveData+DataBinding核心要点1、ViewModel使用要点2、LiveData使用要点3、DataBinding使用要点二、ViewModel+LiveData+DataBinding代码示例1、ViewModel+LiveData代码2、build.gradle构建脚本-启用DataBinding3、DataBinding布局文......
  • 于是他迟到的组合数学学习开始了
    加法原理完成一件事,有\(m\)类方法,对于每类方法有\(s_i\)个方案,则此时总方案数就是\(\sum_{i=1}^ms_i\)。乘法原理完成一件事,有\(n\)个步骤,对于每个步骤有\(s_i\)个方案,则此时总方案数就是\(\prod_{i=1}^ns_i\)。排列从\(n\)个数中选出\(m\)个数的一个排列,记......
  • #yyds干货盘点# LeetCode程序员面试金典:组合总和
    题目:给你一个无重复元素的整数数组 candidates和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target的所有 不同组合,并以列表形式返回。你可以按任意顺序返回这些组合。candidates中的同一个数字可以无限制重复被选取。如果至少一个数字的被......
  • Oracle较长number型数值的科学计数显示
    表中有id列,类型为number,在sqlplus中查询的时候,查询结果的显示方式为科学计数法:ID----------4.5572E+184.5574E+184.5585E+18这样看起来很不直观,而之所以这样显示的原因是在SQL*Plus下,小于等于10位的精度显示的是很直观的形式,大于10位精度的则显示为科学计数的形式。避免......
  • 排列与组合
    目录简介排列乘法原理排列数全排列组合加法原理组合数简介排列就是指从给定个数的元素中取出指定个数的元素进行排序。组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序。排列乘法原理如果完成一个工程需要分\(n\)个步骤,假设\(a_i\)代表第\(i\)个步骤的......
  • 组合逻辑
    抽象 像微处理器的大规模电路有很高的复杂性,可以用抽象和模块化原则将电路视为一个明确定义了接口和功能的黑匣子布尔代数公理 单变量定理逻辑门需要花费成本、功耗和延迟,所以用导线代替门电路是有益处的 同一性定理T1:2输入与门中,若有一个输入总为1,可以删除与门,用......
  • 实战案例 | 双束聚焦离子束(DB-FIB)和透射电子显微镜(TEM)在芯片失效分析中的组合应用
    在做HTGB(高温栅偏测试)项目时,出现了Passdie漏电较小,FaildieIGSS漏电过大(>200nA)的情况。需要对漏电大的芯片进行复测,同时定位漏电所在的位置(热点Hotspot)。之后再利用FIB/TEM对漏电位置进行微观结构/成分分析,找到漏电点所在的膜层;最后基于电镜分析的结果对失效机理做初步判断......
  • a little schemer chapter 9 Y组合算子
    内容参照相关阅读推荐 首先是递归获得阶乘的例子(definef(lambda(x)(cond((=x1)1)(else(*x(f(-x1)))))))对应的lambda(f):(lambda(f)(lambda(x)(cond((=x1)1)(else(*x(f(-x1)))))))......
  • RPM常用命令以及组合使用场景
    本文分享自天翼云开发者社区《RPM常用命令以及组合使用场景》,作者:邬祥钊  当涉及到管理基于RedHat系的Linux系统时,RPM(RedHatPackageManager)是一个常用的软件包管理器。以下是一些常用的RPM命令以及它们的组合使用场景:常用命令:1.rpm-ivhpackage.rpm:安装......