zoukankan      html  css  js  c++  java
  • 求组合数Cnm的的方法

    求一个组合数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));

    }

  • 相关阅读:
    二进制安全(学习笔记)
    rsa
    bugku 隐写 笔记
    dvwa随学笔记
    实验吧 密码学 writeup
    实验吧 隐写 writeup
    实验吧 web题weiteup
    Java数据结构和算法 第二版 课后习题第三章
    自动化测试入门指南(3)-- 入门demo
    自动化测试入门指南(2)-- 环境搭建
  • 原文地址:https://www.cnblogs.com/BeyondAnyTime/p/2508189.html
Copyright © 2011-2022 走看看