组合数:从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(log⁡p)O(\log p)O(logp),其中p=modp=modp=mod,查询时间复杂度为O(1)O(1)O(1)

组合数的计算方法(Combinatorial Number)相关推荐

  1. 组合数求法、卡特兰数

    一.组合数的计算方法 首先组合和排列数的定义在高中阶段已经知晓,这里主要探讨在算法竞赛中的应用.首先,我们通常把 C n m C_{n}^{m} Cnm​写成 ( n m ) \tbinom{n}{m ...

  2. n阶完全图边和顶点关系。_正N边型的完全图被分割成几个多边形

    正N边型的完全图被分割成几个多边形? 这篇文章被分为四个部分 一.知识铺垫 二.在不允许对角线重合的情况下,N边形可以分为多少个多边形 三.正N边形可以分为多少个图形 四.附录(在附录进行总结) 一. ...

  3. 圈的ramsey数研究

    1 引言 1.1 研究内容与意义 "图"最早是人们将具体的事物用一些简单的线条来进行描述.并将这些描述的含义传达给其他人的一种工具.图论这个学科的产生最早应该是在1736年瑞士著名 ...

  4. 排列组合相关笔试面试题(C++)

    一.常考点 含有相同元素的全排列:例如2个a,3个b,4个c可以组成多少个不同的字符串?9!/2!/3!/4!. n个人的全排列:排成一排为n!,排成一圈且考虑旋转带来的差异也为n!,排成一圈但不考虑 ...

  5. 智能网联汽车 自动驾驶地图数据质量规范

    1 范围 本文件规定了全场景下的自动驾驶地图数据质量检测的基本要求.质量检测内容.质量检测指标.质量检测流程.质量检测方法.质量检测结果的判定与质量报告编写的要求等. 本文件适用于自动驾驶地图产品的质 ...

  6. 陈景润定理的数学证明何处寻

    由于时代过于久远,陈景润定理的数学证明与公式推理过程很难寻找. 实际上,陈景润定理的数学证明与公式推导十分复.困难,出乎一般人的想象. 有兴趣者,可搜索该文PDF原文第,查看第5-6页.该文件共有74 ...

  7. 伯努利数、欧拉数与泰勒展开式

    伯努利数和正切函数泰勒展开式 1.伯努利数 2.欧拉数 3.自然幂指数和 4.tan⁡x\tan{x}tanx泰勒展开式 5. 程序应用与计算 参考 1.伯努利数 伯努利数是十八世纪瑞士数学家雅各布· ...

  8. 基本计数、排列组合与Lucas定理

    基本计数原理 加法原理与分类计数法 要完成一件任务,可以经过n种相互无重叠的方案,若第i种方案的方法数为ai,那么完成这件任务的总方案数为 a 1 + a 2 + a 3 + . . . + a n ...

  9. 高效的组合数计算方法

    计算组合数最大的困难在于数据的溢出,对于大于150的整数n求阶乘很容易超出double类型的范围,那么当C(n,m)中的n=200时,直接用组合公式计算基本就无望了.另外一个难点就是效率. 对于第一个 ...

最新文章

  1. java输入字符数组_JAVA中怎样把用户输入的字符串存入数组中?
  2. 图5-5与代码中变量的对应关系
  3. # 保持最外层获取焦点_大事件!沈阳爱尔白内障焕晶诊疗中心正式启用,两位PanOptix三焦点人工晶体植入患者清晰见证!...
  4. Mybatis核心配置文件xml详解
  5. 小学学校计算机室财产登记册,小学财产登记制度
  6. HA:HADOOP高可用机制
  7. C#查找指定窗口的子窗口的句柄
  8. VerbalExpressions
  9. 单元测试界的高富帅,Pytest框架,手把手教学,高阶用法实战
  10. 工具的使用——谷歌浏览器(chrome) (二)
  11. php 禁止转换,php实现十进制、三十六进制转换的函数
  12. python读写音频文件小结
  13. java script特效_javascript 常用特效(40种)
  14. 2017马哥python高级实战班培训推荐
  15. Unity网络编程一: 基于Socket搭建一个服务器
  16. 自学java到可以找工作要多久_自学编程需要多久才能找到工作?
  17. 四川麻将java_四川麻将纯AI算法------最优拆牌
  18. Windows10息屏快的问题解决办法(在更改屏幕和睡眠时间无效的情况下)
  19. 2021年烷基化工艺找解析及烷基化工艺考试试卷
  20. 用Python Matplotlib实现可视化混沌系统

热门文章

  1. 【一笔画完】通关路径算法的Java代码实现V1.0
  2. QT用法--添加外部库文件(lib文件)
  3. opencv3 圆检测
  4. 100集华为HCIE安全培训视频教材整理 | 智能策略
  5. 物流配送进程快递100查询接口
  6. 本科毕业设计(论文)外文翻译--采用多病人协调器集设计方法的远程温度监测装置
  7. 分体式8通道R2000方案智能柜超高频RFID读写器|开发板HXU2889EVB的应用与接口说明
  8. 专家揭秘:补充叶黄素视力毫无改善,原因何在?
  9. android设备驱动之 v4l2,Android设备驱动之——V4L2
  10. 自己的价值=有你的世界-没有你的世界