组合数的计算方法(Combinatorial Number)
组合数:从nnn个不同元素中取出m(m≤n)m(m≤n)m(m≤n)个元素的所有组合的个数,叫做从nnn个不同元素中取出mmm个元素的组合数。计算公式为:
C(n,m)=n!/((n−m)!×m!),where m≤nC(n,m)=n!/((n-m)!\times m!), \text{where}\ m\leq n C(n,m)=n!/((n−m)!×m!),where m≤n
- 性质1:C(n,m)=C(n,n−m)C(n,m)= C(n,n-m)C(n,m)=C(n,n−m)
- 性质2:C(n,m)=C(n−1,m−1)+C(n−1,m)C(n,m)=C(n-1,m-1)+C(n-1,m)C(n,m)=C(n−1,m−1)+C(n−1,m)
第一种方法:打表
根据性质2直接构建一个n×nn\times nn×n的矩阵进行计算:
public class Template {static int mod = (int) 1e9 + 7;static int max = 110;static long[][] com = new long[max][max];public static void main(String[] args) {int n = 100, m = 30;for (int i = 0; i < max; i++) {com[i][0] = com[i][i] = 1;for (int j = 1; j < i; j++) {com[i][j] = (com[i - 1][j - 1] + com[i - 1][j]) % mod;}}System.out.println(com[n][m]);}
}
空间复杂度:O(n2)O(n^2)O(n2)
预处理时间复杂度:O(n2)O(n^2)O(n2),查询时间复杂度:O(1)O(1)O(1)
第二种方法:阶乘无模
根据组合的组合数的计算公式C(n,m)=n!/((n−m)!×m!)C(n,m)=n!/((n-m)!\times m!)C(n,m)=n!/((n−m)!×m!)进行:
public class Template {static int mod = (int) 1e9 + 7;static int max = 110;static long[] fac = new long[max];public static void main(String[] args) {int n = 20, m = 10;fac[0] = 1;for (int i = 1; i < max; i++) {fac[i] = (fac[i - 1] * i);}System.out.println(fac[n] / fac[m] / fac[n - m]);}
}
空间复杂度:O(n)O(n)O(n)
预处理时间复杂度:O(1)O(1)O(1),查询时间复杂度:O(n)O(n)O(n)
由于涉及除法,无法直接取模,所以引入乘法逆元。
第三种方法:乘法逆元
逆元:对于aaa和ppp(aaa和ppp互素),若a∗b%p≡1a*b\%p\equiv1a∗b%p≡1,则称bbb的最小正整数解为aa%pa的逆元。
当求解(a/b)%p(a/b)\%p(a/b)%p,如果知道b%pb\%pb%p的逆元为ccc,那么可以转化为(a/b)%p=a∗c%p=(a%p)(c%p)%p(a/b)\%p=a*c\%p=(a\%p)(c\%p)\%p(a/b)%p=a∗c%p=(a%p)(c%p)%p。暴力做法:
public class Template {static int mod = (int) 1e9 + 7;static int max = 110;static long[] fac = new long[max];static long[] inv = new long[max];public static void main(String[] args) {int n = 100, m = 30;inv[0] = fac[0] = 1;for (int i = 1; i < max; i++) {fac[i] = (fac[i - 1] * i) % mod;inv[i] = inv(fac[i]);}System.out.println(((fac[n] * inv[m]) % mod * inv[n - m]) % mod);}public static long inv(long a) {for (int x = 1; x < mod; x++) {if (a * x % mod == 1) return x;}return 0;}
}
空间复杂度:O(n)O(n)O(n)
预处理时间复杂度:O(p)O(p)O(p),其中p=modp=modp=mod,查询时间复杂度:O(1)O(1)O(1)
第四种方法:乘法逆元+快速幂+阶乘
费马小定理:对于a和素数p,满足ap−1%p≡1a^{p-1}\%p\equiv 1ap−1%p≡1。
因为ap−1=ap−2∗aa^{p-1}=a^{p-2}*aap−1=ap−2∗a,所以有ap−2∗a%p≡1a^{p-2}*a\%p\equiv 1ap−2∗a%p≡1。根据逆元的定义可知,ap−2a^{p-2}ap−2是aaa的逆元。因此可以将求解逆元的问题转换为ap−2a^{p-2}ap−2的快速幂问题。
public class Template {static int mod = (int) 1e9 + 7;static int max = 110;static long[] fac = new long[max];static long[] inv = new long[max];public static void main(String[] args) {int n = 100, m = 30;inv[0] = fac[0] = 1;for (int i = 1; i < max; i++) {fac[i] = (fac[i - 1] * i) % mod;inv[i] = inv(fac[i]);}System.out.println(((fac[n] * inv[m]) % mod * inv[n - m]) % mod);}public static long pow(long a, long b) {long ans = 1;while (b > 0) {if ((b & 1) == 1) ans = (ans * a) % mod;a = a * a % mod;b = b >> 1;}return ans;}public static long inv(long a) {return pow(a, mod - 2);}
}
空间复杂度:O(n)O(n)O(n)
预处理时间复杂度:O(logp)O(\log p)O(logp),其中p=modp=modp=mod,查询时间复杂度为O(1)O(1)O(1)
组合数的计算方法(Combinatorial Number)相关推荐
- 组合数求法、卡特兰数
一.组合数的计算方法 首先组合和排列数的定义在高中阶段已经知晓,这里主要探讨在算法竞赛中的应用.首先,我们通常把 C n m C_{n}^{m} Cnm写成 ( n m ) \tbinom{n}{m ...
- n阶完全图边和顶点关系。_正N边型的完全图被分割成几个多边形
正N边型的完全图被分割成几个多边形? 这篇文章被分为四个部分 一.知识铺垫 二.在不允许对角线重合的情况下,N边形可以分为多少个多边形 三.正N边形可以分为多少个图形 四.附录(在附录进行总结) 一. ...
- 圈的ramsey数研究
1 引言 1.1 研究内容与意义 "图"最早是人们将具体的事物用一些简单的线条来进行描述.并将这些描述的含义传达给其他人的一种工具.图论这个学科的产生最早应该是在1736年瑞士著名 ...
- 排列组合相关笔试面试题(C++)
一.常考点 含有相同元素的全排列:例如2个a,3个b,4个c可以组成多少个不同的字符串?9!/2!/3!/4!. n个人的全排列:排成一排为n!,排成一圈且考虑旋转带来的差异也为n!,排成一圈但不考虑 ...
- 智能网联汽车 自动驾驶地图数据质量规范
1 范围 本文件规定了全场景下的自动驾驶地图数据质量检测的基本要求.质量检测内容.质量检测指标.质量检测流程.质量检测方法.质量检测结果的判定与质量报告编写的要求等. 本文件适用于自动驾驶地图产品的质 ...
- 陈景润定理的数学证明何处寻
由于时代过于久远,陈景润定理的数学证明与公式推理过程很难寻找. 实际上,陈景润定理的数学证明与公式推导十分复.困难,出乎一般人的想象. 有兴趣者,可搜索该文PDF原文第,查看第5-6页.该文件共有74 ...
- 伯努利数、欧拉数与泰勒展开式
伯努利数和正切函数泰勒展开式 1.伯努利数 2.欧拉数 3.自然幂指数和 4.tanx\tan{x}tanx泰勒展开式 5. 程序应用与计算 参考 1.伯努利数 伯努利数是十八世纪瑞士数学家雅各布· ...
- 基本计数、排列组合与Lucas定理
基本计数原理 加法原理与分类计数法 要完成一件任务,可以经过n种相互无重叠的方案,若第i种方案的方法数为ai,那么完成这件任务的总方案数为 a 1 + a 2 + a 3 + . . . + a n ...
- 高效的组合数计算方法
计算组合数最大的困难在于数据的溢出,对于大于150的整数n求阶乘很容易超出double类型的范围,那么当C(n,m)中的n=200时,直接用组合公式计算基本就无望了.另外一个难点就是效率. 对于第一个 ...
最新文章
- java输入字符数组_JAVA中怎样把用户输入的字符串存入数组中?
- 图5-5与代码中变量的对应关系
- # 保持最外层获取焦点_大事件!沈阳爱尔白内障焕晶诊疗中心正式启用,两位PanOptix三焦点人工晶体植入患者清晰见证!...
- Mybatis核心配置文件xml详解
- 小学学校计算机室财产登记册,小学财产登记制度
- HA:HADOOP高可用机制
- C#查找指定窗口的子窗口的句柄
- VerbalExpressions
- 单元测试界的高富帅,Pytest框架,手把手教学,高阶用法实战
- 工具的使用——谷歌浏览器(chrome) (二)
- php 禁止转换,php实现十进制、三十六进制转换的函数
- python读写音频文件小结
- java script特效_javascript 常用特效(40种)
- 2017马哥python高级实战班培训推荐
- Unity网络编程一: 基于Socket搭建一个服务器
- 自学java到可以找工作要多久_自学编程需要多久才能找到工作?
- 四川麻将java_四川麻将纯AI算法------最优拆牌
- Windows10息屏快的问题解决办法(在更改屏幕和睡眠时间无效的情况下)
- 2021年烷基化工艺找解析及烷基化工艺考试试卷
- 用Python Matplotlib实现可视化混沌系统