【问题标题】:finding combinatorial of large numbers寻找大数的组合
【发布时间】:2011-01-23 16:53:16
【问题描述】:

在 N 可能非常大(N ~ 10^18)的 N 个礼物中,找到可以选择 k 个礼物的方法数量的有效方法是什么?也就是说我们要计算N(C)K或者N选K。K也可以是N的量级。

【问题讨论】:

标签: algorithm math combinations largenumber


【解决方案1】:

我想没有快速的方法来计算这么大的数字。你可以使用Stirling's formula来近似它

【讨论】:

  • 如果我们不知道 k 与 n 的比较情况,斯特林公式将毫无用处。
  • @Alexandre C.:嗯,你怎么能这么说?斯特林公式近似于n!。所以你近似 n!, k! and (n - k)! 并得到一个近似 n! / (k! * (n - k)!)。如果你想对C(n, k) 的行为有一个渐近的感觉,那么,是的,你需要kn 之间的关系,但要近似,不。
  • @Jason:计算 3 倍 log gamma 非常快,大概可以媲美 pow + exp + sqrt。斯特林公式(以及斯特林级数)的强大之处在于,当您同时知道 k 和 n 的行为时,它可以让您获得准确的渐近线。您有更好的选择来近似阶乘。 en.wikipedia.org/wiki/Lanczos_approximation 是一个好的开始。
  • @Alexandre C.:我不否认这一点。如果我们无法将kn 进行比较,我否认您的说法,即斯特林公式毫无用处。
  • @Alexandre C.:看,这就是我不同意你的地方。我并不否认您声称您给出的近似值更好(这是众所周知的,它是直接输出的数值食谱)。我否认你声称斯特林近似是无用的。
【解决方案2】:

只有当您有更多的渐近信息(例如k ~ n / 3k ~ log n)时,斯特林公式才有用。如果没有关于您的具体问题的进一步信息,您将不会得出任何关于斯特林公式的信息。

对于您所说的问题,当 k 和 n 很大时(即使它们不大)计算 C(n, k) 的最直接方法是使用

log C(n, k) = log (n!) - (log (k!) + log ((n - k)!))

n! = gamma(n + 1).

事实上,实现 log gamma 很容易,然后你就有了

C(n, k) = exp (f(n + 1) - f(k + 1) - f(n - k + 1))

f = log gamma.

您可以在 Numerical Recipes 中找到用于计算 log gamma 的数值算法,旧版本可用 there,您将在第 6 章中找到示例实现。

【讨论】:

  • 另请注意,对于许多应用程序,您甚至可能更乐意存储ln(C(n, k)) = lngamma(n+1) - lngamma(k+1) - lngamma(n-k+1)。溢出的机会要小得多。
  • 你能解释一下什么是伽玛吗?我不熟悉它作为标准功能?还是只是由 gamma(n+1) = n! 定义?
  • @Chris: Gamma(x) = 积分(exp(-t) t^(x - 1) dt, t = 0..infinity)。公式 Gamma(n) = (n-1)!通过部分整合而成立。有一些快速的方法可以计算 Gamma 或 log Gamma。
  • 啊,谢谢。这现在敲响了一些模糊的钟声。我认为它可能是一个在那些离散点上工作的连续函数,但总是很容易检查。 :)
【解决方案3】:

由于多样性是生活的调味品,下面是另一种方法。价值 (N 选择 K)/2^N 接近具有均值 N/2 和标准偏差 Sqrt[N]/2 的正态分布,而且它的速度非常快。因此,我们可以将(N 选择 K)近似为 2^N * Normdist(x,0,1)/std 其中 x =( k - N/2)/std 和 std 是 Sqrt[N]/2。
Normdist(x,0,1) = Exp(-x^2/2)*1/(Sqrt(2*Pi))

就误差而言,数字越大,这应该会变得更好,并且使用 N 作为 113(?) 的快速检查显示最大误差占最大系数的百分比小于 0.3%。

并没有声称它比使用斯特林公式更好,但认为它可能会避免一些 n^n 计算,并且计算这些系数的对数是一个非常简单的计算。

【讨论】:

  • 感谢 Alexandre,只是将这一切添加到 Log(N 选择 K) = (4*k - (4*Power(k,2))/n + Log(2) + n*(-1 + Log(4)) - Log(n*Pi))/2 这应该是这里最快的算法(如果不是最好的)。
【解决方案4】:

C(n, k) 的值可以接近2^n。 (嗯,数量级更小,但这在这里并不重要)。

重要的是要存储数字2^(10^18),您需要10^18 位或~ 10^17 字节。
您可能需要调整问题定义,因为没有这样的计算机。

其他人已经指出了近似公式,您可以将结果存储为浮点数,因此不会花费过多的内存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多