Algorithm 求大数的组合

Algorithm 求大数的组合,algorithm,math,combinations,largenumber,Algorithm,Math,Combinations,Largenumber,从N个礼物中选择k个礼物的有效方法是什么,其中N可以非常大(N~10^18)。也就是说,我们必须计算N(C)K或N选择K。K也可以是N的数量级。我想没有快速的方法来计算这么大的数。您可以使用来近似它C(n,k)的值可以接近2^n。(好吧,数量级更小,但这在这里并不重要) 重要的是要存储数字2^(10^18),您需要10^18位或~10^17字节。 您可能需要调整问题定义,因为没有这样的计算机 其他人已经指出了近似公式,在这里可以将结果存储为浮点数,这样就不会花费过多的内存。Stirling公式只

从N个礼物中选择k个礼物的有效方法是什么,其中N可以非常大(N~10^18)。也就是说,我们必须计算N(C)K或N选择K。K也可以是N的数量级。

我想没有快速的方法来计算这么大的数。您可以使用来近似它
C(n,k)
的值可以接近
2^n
。(好吧,数量级更小,但这在这里并不重要)

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


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

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

对于前面提到的问题,当k和n很大(甚至不是很大)时,计算C(n,k)最直接的方法是使用

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

事实上,log gamma的实现非常容易,然后您就可以

C(n, k) = exp (f(n + 1) - f(k + 1) - f(n - k + 1))
其中
f=log gamma


你可以在数值配方中找到计算对数伽马的数值算法,有一个旧版本可用,你可以在第6章中找到一个示例实现。

由于多样性是生活的调味品,另一种方法如下。价值 (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计算,而计算这些系数的对数是一个非常简单的计算。

如果我们不知道k和n的比较,看看斯特林公式是没有用的。@Alexandre C:哈,你怎么能这么说?斯特林公式近似于
n。所以你大概是
n!,K和(n-k)
并获得
n!/(k!*(n-k)!)
。如果你想对
C(n,k)
的行为有一个渐近的感觉,那么,是的,你需要
k
n
之间的关系,但是为了近似,不。@Jason:计算3倍log gamma非常快,可能与pow+exp+sqrt相当。斯特林公式(和斯特林级数)的威力在于,当你知道k和n的行为时,它可以让你得到精确的渐近解。对于近似阶乘,您有更好的选择。“一个好的开始是,”亚历山大C:我不否认这一点。如果我们不能将
k
n
进行比较,我就否认你所说的斯特林公式是无用的。@Alexandre C:看,这就是我不同意你的观点。我并不否认你的说法,你给出的近似值更好(这是众所周知的,这是直接从数值公式中得出的)。我否认你所说的斯特林近似是无用的。还请注意,对于许多应用程序,存储
ln(C(n,k))=lngamma(n+1)-lngamma(k+1)-lngamma(n-k+1)
可能会让你更开心。溢出的可能性要小得多。你能解释一下伽马是什么吗?我不熟悉它的标准功能?或者它只是由gamma(n+1)=n!定义的@克里斯:伽马(x)=积分(exp(-t)t^(x-1)dt,t=0..无穷大)。伽马(n)=(n-1)!通过部分积分保持。有很多计算伽马或对数伽马的快速方法。啊,谢谢。现在这听起来有些模糊。我想这可能是一个连续的函数,在这些离散点上工作,但检查起来总是很好。:)感谢Alexandre,只要加上这些,就可以得到Log(N选择K)=(4*K-(4*Power(K,2))/N+Log(2)+N*(-1+Log(4))-Log(N*Pi))/2,这应该是这里最快的算法(如果不是最好的话)。
C(n, k) = exp (f(n + 1) - f(k + 1) - f(n - k + 1))