求一个组合数Cnm的值,Cnm= n! /(n-m)!*m!化简的结果为
Cnm = (n*(n-1)*…*(n-m+1))/m!
这个直接求根据公式直接求显然是不行的,当n和m较大时,显然是要溢出的。目前知道两种解决这种题的思路:
思路一:可以利用递推关系式Cnm = C(n)(m-1) + C(n-1)(m-1)来实现,这样初始化前几个组合数,在根据题目要求处理的最大n和m值,递推求出所有的Cnm,并保存。
实现方法以后补上。
思路二:为了避免直接计算n的阶乘,可以直接对公式两边取对数,于是得到:ln(C(n,m)) = ln(n!) - ln(m!) - ln( (n-m)! )
对数有性质:ln(x*y) = ln(x) + ln(y),因此转化成:
Ln(n!) = ln(1) + ln(2) + …+ln(n);
同理消去重叠的部分得到:
Cnm = (n*(n-1)*…*(n-m+1))/m!
因此这个算法时间复杂度仍然是 O( m ),虽然浮点计算比整数计算要慢,但解决了整数计算的溢出问题。
代码实现(转)
double cnm_lg(int n,int m)
{
int i;
double s1=0.0,s2=0.0;
for(i=1;i<=m;i++)
s1 += log(i);
for(i=n-m+1;i<=n;i++)
s2 += log(i);
return s2-s1;
}
double cnm_double(int n,int m)
{
if(m > n/2)
m = n-m;
return exp(cnm_lg(n,m));
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架