前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >用计算机算组合数_计算组合数

用计算机算组合数_计算组合数

作者头像
全栈程序员站长
发布于 2022-09-20 11:12:11
发布于 2022-09-20 11:12:11
5540
举报

大家好,又见面了,我是你们的朋友全栈君。

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

对于第一个数据溢出的问题,可以这样解决。因为组合数公式为:

  C(n,m) = n!/(m!(n-m)!)

为了避免直接计算n的阶乘,对公式两边取对数,于是得到:

ln(C(n,m)) = ln(n!)-ln(m!)-ln((n-m)!)

进一步化简得到:

这样我们就把连乘转换为了连加,因为ln(n)总是很小的,所以上式很难出现数据溢出。

为了解决第二个效率的问题,我们对上式再做一步化简。上式已经把连乘法变成了求和的线性运算,也就是说,上式已经极大地简化了计算的复杂度,但是还可以进一步优化。从上式中,我们很容易看出右边的3项必然存在重复的部分。现在我们把右边第一项拆成两部分:

这样,上式右边第一项就可以被抵消掉,于是得到:

上式直接减少了2m次对数计算及求和运算。但是这个公式还可以优化。对于上面公式里的求和,当m<n/2时,n-m是一个很大的数,但是当m>n/2时,n-m就会小很多。我们知道:

C(n,m) = C(n,n-m)

那么通过这个公式,我们可以把小于n/2的m变为大于n/2的n-m再进行计算,结果是一样的,但是却能减少计算量。

当计算出ln(C(n,m))后,只需要取自然对数,就可以得到组合数:

C(n,m) = exp(ln(C(n,m)))

这样就完成了组合数的计算。

用这种方法计算组合数,如果只计算ln(C(n,m))的话,n可以取到整型数据的极限值65535,

ln(C(65535,32767)) = 45419.6

而计算时间只需要0.01ms。当然,如果要取对数得到最终的组合数的话,n的取值就不能达到这么大了。但是这种算法仍然可以保证n取到1000以上,而不是开头说的150这个极限值。例如:

C(1000,500) = 2.70288e+299

计算时间仍然小于0.01ms。

采用这种算法,不仅n的取值范围大,而且计算速度高,不像用递归算法实现这个问题的时候,很容易陷入递归层次太深而导致计算时间太长。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/166933.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
B - 组合数的计算【C++】
给定n组整数(a,b),计算组合数C(a,b)的值。如C(3,1)=3,C(4,2)=6。
来杯Sherry
2023/05/25
3200
组合数递推的计算方法 c语言,组合数公式的递推公式
任意选择m中的某个备选元素为特殊元素,从m中选n个元素可以由此特殊元素的被包含与否分成两类情况,即n个被选择元素包含了特殊元素和n个被选择元素不包含该特殊元素。
全栈程序员站长
2022/09/13
1.7K0
利用Python进行组合数计算
开学几个星期了emmm 作业一如既往的多。。。。。。。 在做数学的时候经常要算组合数,奈何我的计算机太水了(其实是我懒哈哈) 正好最近学Python学的差不多哈哈,所以寻思着能不能用Python实现一下(虽然我用不上哈哈) 说干就干,在学校宿舍被窝里用QPython捣鼓了好一会(我菜),最终就实现了哈哈哈 下面我们来看看吧~
HCG_Sky
2020/07/24
3.3K0
组合数公式
\[\binom{n}{k}+\binom{n}{k-1}=\binom{n+1}{k} \]
全栈程序员站长
2022/09/08
4140
求组合数
分析:  C(10, 3) = C(10, 2) * 8 / 3 = C(10, 1) * 9 * 8 / (3 * 2) = C(10, 0) * 10 * 9 * 8 / (3 * 2 * 1) = 1 * 10 * 9 * 8 / (3 * 2 * 1) = 120
海天一树
2018/07/25
6280
求组合数
C++数学与算法系列之排列和组合
本文将聊聊排列和组合,排列组合是组合学最基本的概念,排列组合在程序运用中也至关重要。
一枚大果壳
2022/12/20
1.2K0
C++数学与算法系列之排列和组合
文心一言 VS 讯飞星火 VS chatgpt (38)-- 算法导论5.4 2题
这是一个典型的鸽巢原理(Pigeonhole Principle)问题。假设每次投球时,每个箱子有1/b的概率被选中。我们设投球次数为x。
福大大架构师每日一题
2023/06/21
1570
文心一言 VS 讯飞星火 VS chatgpt (38)-- 算法导论5.4 2题
练习2-18 求组合数 (15分)
建议定义和调用函数fact(n)计算n!,其中n的类型是int,函数类型是double。
C you again
2021/03/16
7020
练习2-18 求组合数 (15分)
【组合数学】组合恒等式 ( 八个组合恒等式回顾 | 组合恒等式 积 1 | 证明 | 使用场景 | 求组合数通用方法 )
组合数解析 : 这是两个组合数的乘法 , 使用的是 分步计数原理 , 对应乘法法则 ;
韩曙亮
2023/03/28
1.6K0
排列组合的一些公式及推导(非常详细易懂)[通俗易懂]
分类计数原理:做一件事,有\(n\)类办法,在第\(1\)类办法中有\(m_1\)种不同的方法,在第\(2\)类办法中有\(m_2\)种不同的方法,…,在第\(n\)类办法中有\(m_n\)种不同的方法,那么完成这件事共有\(N=m_1+m_2+…+m_n\)种不同的方法。
全栈程序员站长
2022/09/20
3.9K0
C++系列-第3章循环结构-29-累乘和连除
在线练习: http://noi.openjudge.cn/ https://www.luogu.com.cn/
IT从业者张某某
2024/01/20
5360
C++系列-第3章循环结构-29-累乘和连除
【组合数学】排列组合 ( 多重集组合数 | 所有元素重复度大于组合数 | 多重集组合数 推导 1 分割线推导 | 多重集组合数 推导 2 不定方程非负整数解个数推导 )
这里就将 多重集的组合问题 , 转化成了 另外一个多重集的全排列问题 , 多重集全排列是有公式的 ;
韩曙亮
2023/03/28
8830
【组合数学】排列组合 ( 多重集组合数 | 所有元素重复度大于组合数 | 多重集组合数 推导 1 分割线推导 | 多重集组合数 推导 2 不定方程非负整数解个数推导 )
【组合数学】组合恒等式总结 ( 十一个组合恒等式 | 组合恒等式证明方法 | 求和方法 ) ★
② 归纳步骤 : 根据 数学归纳法的种类 , 进行不同方式的证明 , 这里有 第一数学归纳法 和 第二数学归纳法 两种归纳法 ;
韩曙亮
2023/03/28
2.1K0
K - Wand FZU - 2282 【 组合数 + 错排 】
N wizards are attending a meeting. Everyone has his own magic wand. N magic wands was put in a line, numbered from 1 to n(Wand_i owned by wizard_i). After the meeting, n wizards will take a wand one by one in the order of 1 to n. A boring wizard decided to reorder the wands. He is wondering how many ways to reorder the wands so that at least k wizards can get his own wand.
Lokinli
2023/03/09
1770
Python版组合数计算方法优化思路和源码
总体说明:本文的优化思路并不局限于Python,但C、C++、C#、Java等语言无法使用内置类型直接表示大整数,需要通过数组等特定形式并自己实现大整数乘除法才能实现,因此本文只介绍Python语言的实现。 按照标准的组合数公式,再结合Python标准库的阶乘函数factorial(),很容易写出下面的代码: def cni(n, i): from math import factorial return factorial(n) // factorial(i) // factorial(n-i) 但是
Python小屋屋主
2018/04/16
2.2K0
组合数的各种性质和定理
从m个物品里选出n个的方案数,记作 Cnm C m n C_m^n,即为组合数 组合数有很多很多的性质和定理。。。 注意由于本人沉迷玩梗无法自拔,如果看见您看不懂的梗请随意跳过。
全栈程序员站长
2022/09/13
9400
cf932E. Team Work(第二类斯特灵数 组合数)
$$m^n = \sum_{i = 0}^m C_{n}^i S(n, i) i!$$
attack
2018/09/30
4040
【组合数学】计数模型、常见组合数与组合恒等式 ★★
除端点外 , 不接触对角线的非降路径数 参考 : 【组合数学】非降路径问题 ( 限制条件的非降路径数 )
韩曙亮
2023/03/28
7280
【组合数学】生成函数 ( 使用生成函数求解不定方程解个数 )
不定方程解的个数 , 推导过程参考 : 【组合数学】排列组合 ( 多重集组合数 | 所有元素重复度大于组合数 | 多重集组合数 推导 1 分割线推导 | 多重集组合数 推导 2 不定方程非负整数解个数推导 ) 二、多重集组合 所有元素重复度大于组合数 推导 2 ( 不定方程非负整数解个数推导 )
韩曙亮
2023/03/28
7640
洛谷P3746 [六省联考2017]组合数问题
题目描述 组合数 C_n^mCnm​ 表示的是从 n 个互不相同的物品中选出 m 个物品的方案数。举个例子,从 (1;2;3) 三个物品中选择两个物品可以有 (1;2);(1;3);(2;3) 这三种选择方法。根据组合数的定义,我们可以给出计算组合数 C_n^mCnm​ 的一般公式: C_n^m = \frac{n!}{m!(n-m)!}Cnm​=m!(n−m)!n!​ 其中 n! = 1 × 2 × · · · × n。(特别的,当 n = 0 时, n! = 1 ,当 m > n 时, C_n^m =0
attack
2018/04/10
7210
推荐阅读
相关推荐
B - 组合数的计算【C++】
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档