【发布时间】:2011-01-23 16:53:16
【问题描述】:
在 N 可能非常大(N ~ 10^18)的 N 个礼物中,找到可以选择 k 个礼物的方法数量的有效方法是什么?也就是说我们要计算N(C)K或者N选K。K也可以是N的量级。
【问题讨论】:
标签: algorithm math combinations largenumber
在 N 可能非常大(N ~ 10^18)的 N 个礼物中,找到可以选择 k 个礼物的方法数量的有效方法是什么?也就是说我们要计算N(C)K或者N选K。K也可以是N的量级。
【问题讨论】:
标签: algorithm math combinations largenumber
我想没有快速的方法来计算这么大的数字。你可以使用Stirling's formula来近似它
【讨论】:
n!。所以你近似 n!, k! and (n - k)! 并得到一个近似 n! / (k! * (n - k)!)。如果你想对C(n, k) 的行为有一个渐近的感觉,那么,是的,你需要k 和n 之间的关系,但要近似,不。
k 与n 进行比较,我否认您的说法,即斯特林公式毫无用处。
只有当您有更多的渐近信息(例如k ~ n / 3 或k ~ 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)。溢出的机会要小得多。
由于多样性是生活的调味品,下面是另一种方法。价值
(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 计算,并且计算这些系数的对数是一个非常简单的计算。
【讨论】:
C(n, k) 的值可以接近2^n。 (嗯,数量级更小,但这在这里并不重要)。
重要的是要存储数字2^(10^18),您需要10^18 位或~ 10^17 字节。
您可能需要调整问题定义,因为没有这样的计算机。
其他人已经指出了近似公式,您可以将结果存储为浮点数,因此不会花费过多的内存。
【讨论】: