【发布时间】:2012-02-20 23:58:43
【问题描述】:
我想优化我的程序的一部分,我正在计算高达 K 的二项式系数的总和。即
C(N,0) + C(N,1) + ... + C(N,K)
由于值超出了数据类型(long long)可以支持的范围,我将计算值 mod M 并正在寻找执行此操作的程序。
目前,我已经使用 Pascal 的三角形完成了它,但它似乎需要一些负载。所以,我想知道是否还有其他有效的方法可以做到这一点。我考虑过卢卡斯定理,尽管我的 M 已经足够大,以至于 C(N,k) 失控了!
任何关于我如何以不同方式执行此操作的指针,也许可以用其他一些简洁的总和表达式来计算整个总和。如果不是,我将把它留给 Pascal 的三角形方法本身。
谢谢,
这是我目前所拥有的O(N^2):
#define MAX 1000000007
long long NChooseK_Sum(int N, int K){
vector<long long> prevV, V;
prevV.push_back(1); prevV.push_back(1);
for(int i=2;i<=N;++i){
V.clear();
V.push_back(1);
for(int j=0;j<(i-1);++j){
long long val = prevV[j] + prevV[j+1];
if(val >= MAX)
val %= MAX;
V.push_back(val);
}
V.push_back(1);
prevV = V;
}
long long res=0;
for(int i=0;i<=K;++i){
res+=V[i];
if(res >= MAX)
res %= MAX;
}
return res;
}
【问题讨论】:
-
我一直使用 Pascal 的三角形,我认为你很快就会遇到舍入错误,尤其是 32 位整数,但它在第 20 行之前运行良好,所以很适合我的需要。
-
N、K和M的大概取值范围是多少?另外,你能读懂 SML-caml-F# 吗?如果对你有用的话,我有 F# 中的代码。
-
如果
K比N小很多,你可以通过在K停止内循环来获得相当多的收益,如果K接近N,通过停止在N-K并使用所有二项式系数之和为2^N的事实。但是,如果您真的需要快速,部分 deux 的建议(使用模逆)可以在 O(K*log(min(K,MAX))) 步骤中为您提供总和(模MAX)。 (如果K >= MAX,则需要小心。) -
你绝对可以通过将向量更改为静态数组来做得更好。可能会花费太多时间来分配。
-
@kkm - 恐怕我不了解 SML-caml-F#,但欢迎您使用此处的方法编写代码。 1
标签: c++ algorithm binomial-coefficients