【问题标题】:C++: Combination/multiset functions (factorial overflow)C++:组合/多集函数(阶乘溢出)
【发布时间】:2016-03-24 19:59:11
【问题描述】:

我必须实现一个问题,从一组 n 个元素中计算 m 个元素的组合和多组。 它们的公式如下:

问题是阶乘很容易溢出,那么这个问题基本上有什么解决办法呢?

由于它是 TopCoder 中问题的子问题,因此我有以下限制:

1) 程序必须用 C++ 编写。

2) 我无法加载外部库。

【问题讨论】:

  • 重写 C(n,m) 的显式项。您的问题中的那个通常在理论上是最方便使用的,但是当您实际必须计算它时,有一个不会很快溢出。

标签: c++ algorithm combinatorics factorial


【解决方案1】:

你真的不需要直接计算n!,这很容易溢出。自从

C(n,m) = C(n-1, m-1) + C(n-1,m)
C(n,0) = C(n,n) =1

您可以建立一个大小为(n+1,m+1) 的表格,并使用动态规划以自下而上的方式建立表格。

算法伪代码可能如下:

for i ← 0 to n do  // fill out the table row wise
      for j = 0 to min(i, m) do
          if j==0 or j==i then C[i, j] ← 1 
          else C[i, j] ← C[i-1, j-1] + C[i-1, j] 
return C[n, m]

如果您声明 c(n,m) 为 long double 并且 n 不是那么大,那么这种方式应该可以工作。否则,您需要定义自己的 BigInteger 类以避免溢出,并定义 + 运算符对 BigInteger 的工作方式,BigInteger 通常表示为字符数组或字符串。

【讨论】:

  • 应该是第二个中的 j 作为条件还是我错过了一点?
  • @KudayarPirimbaev 抱歉,错字,第二个循环变量应该是 j,而不是 i。我更新了代码。很好,谢谢!
  • 好的,谢谢,不敢相信我还没有想出这种不同的方法
  • 我喜欢那些时髦的小 符号。
【解决方案2】:

因子是相当大的数字(它们不适合 64 位字)。所以你需要使用bignums(任意精度算术)来完整地计算它们。考虑为此目的使用GMPlib(或在语言和实现中编写代码,例如带有SBCL的Common Lisp,它本机提供它们)

另请参阅 thisthat 对与您的问题非常相似的问题的回答。

【讨论】:

  • 那么如果我不能使用外部库而必须用 c++ 编写呢?因为我是用 TopCoder 写的,所以有一些限制
  • @KudayarPirimbaev:TopCoder 至少允许您使用 C++、Java、C# 和 VB。如果你想走那条路,其中 4 个中有 3 个在其标准库中内置了任意长度的整数。
  • 因为我只知道 c++,我不能简单地改变语言来解决一个问题,但我知道它们是构建的,谢谢,只是为了扩展我的编程范围,我有约束要求,因为学习新事物,你知道的
【解决方案3】:

不要使用递归方法来计算可能导致堆栈溢出的阶乘,而是使用迭代方法!即使对于更大的数字,这也可以为您节省溢出。

【讨论】:

  • 数字溢出,而不是堆栈
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-14
  • 1970-01-01
  • 1970-01-01
  • 2020-06-27
  • 2015-01-08
相关资源
最近更新 更多