【发布时间】:2017-02-15 05:18:45
【问题描述】:
我正在尝试在O(N) 中计算此值而不会溢出(使用 C++)
为了澄清,n,r 是事先给出的,我试图在O(N) 中找到(n,r) 对的一个实例的答案
这是我的试验:
- 使用
O(N)计算ans = n!/(r!(n-r)!2^n) - 让
c = ans,用O(N)修改c:c /= (n-p); c*=(p+1)为p = r-1 to 0。为每个步骤添加c到ans
基本上,我首先使用O(N) 计算最后一项,然后使用滑动窗口之类的东西来查找倒数第二个,然后是下一个……直到第一个。在这个过程中总结它们。
虽然看起来是正确的,但实际运行时间仍然比我预期的要慢。所以我想知道这个公式有什么特殊的已知技巧可以提高性能吗?如果没有,那么有没有办法减少常数因子? (基于以下sn-p)
另一个大问题是我面临一个困境:我不能单独计算 2^(-n) 或 nCr 大 n,否则它会下溢/溢出。这就是为什么我尝试计算2^(-n) * The last term in the summation 和希望效果会相互抵消,这样我就不会在整个过程中出现下溢/溢出。有什么方法可以100%保证不会下溢/上溢?
(如果可能,我想避免使用大整数库)
// c++ code snippet to demonstrate the idea
double ans = 1;
for(int p=n; p>=1; p--){
ans *= p;
ans /= 2;
if(p <= r) ans /= p;
if(p <= n-r) ans /= p;
}
// now ans = n!/(r!(n-r)!2^n)
// use O(N) more time to find the ultimate ans: summation (n!/(r!(n-r)!2^n)) for r >= 0
double c = ans;
for(int p = r-1; p >= 0; p--){
c /= (n-p);
c *= (p+1);
// Each new c is the next term: n!/((r-1)!(n-r+1)!2^n)
ans += c;
}
【问题讨论】:
-
等等... sum 并没有说明 summation 变量是什么。如果
n和r都是常量,而求和中的表达式是n choose r,那么您似乎只是在对一个常量求和。 -
@user2357112 sum(nC0, nC1..nCr),这里的图不对,我去编辑一下
-
您使用
double是否意味着您对近似值感到满意? -
@rici yes 如果近似值的精度至少为 10^-8...
标签: c++ algorithm math combinatorics