在O(logn)时间内找到从k = 0到n的x ^ k之和

时间:2015-03-15 00:29:47

标签: c algorithm big-o

所以我的问题是如何在C中更具体地做到这一点。我知道O(logn)通常意味着我们将以某种方式拆分其中一个参数来使用递归。

我想要达到的是x n 的k = 0到n的总和。 例如,exponent_sum(x,n)将是这种情况下的参数。

然后,

exponent_sum(4, 4)将是4 0 + 4 1 + 4 2 + 4 3 + 4 4 = 341。

我不知道从哪里开始。一些提示将非常感激。

5 个答案:

答案 0 :(得分:20)

查看总和的一种方法是基数x中包含全1的数字。

例如,4 4 + 4 3 + 4 2 + 4 1 + 4 0 在基数4中为11111。

在任何基数中,1s的字符串将等于1,后跟一个相同数字的0,减1的字符串除以基数减去1.

例如:

    基础10中的
  • :(1000-1)/ 9 = 999/9 = 111
  • 基本16中的
  • :( 0x10000 - 1)/ 0xF = 0xFFFF / 0xF = 0x1111
  • 基础8中的
  • :(0100-1)/ 7 = 077/7 = 011

所以把这些放在一起,我们可以概括一下

exponent_sum(x,n)=(x (n + 1) - 1)/(x - 1)

例如,exponent_sum(4,4)=(4 5 - 1)/ 3 = 1023/3 = 341

因此,它的大O复杂度与计算x n

相同

答案 1 :(得分:5)

让我为完整性添加另一个证据:

s = 1 + x 1 + x 2 + ... + x n

然后

xs = x(1 + x 1 + x 2 + ... + x n )= x 1 < / sup> + x 2 + ... + x n + x n + 1 = s - 1 + x n + 1

解决s

(x - 1)s = x n + 1 - 1,

s =(x n + 1 - 1)/(x - 1)

答案 2 :(得分:1)

查看解决方案的另一种方法是这样的:假设总和为S,写为

S = 1 + x + x^2 + ... + x^k

然后,如果我们将它的两边乘以x,我们得到

S*x = x * (1 + x + x^2 + ... + x^k)
    = x + x^2 + ... + x^k + x^(k+1)

然后向双方添加1

S*x + 1 = 1 + x + x^2 + ... + x^k + x^(k+1)
        = (1 + x + x^2 + ... + x^k) + x^(k+1)
        = S + x^(k+1)

表示

S*x - S = x^(k+1) - 1
S*(x - 1) = x^(k+1) - 1

所以

S = (x^(k+1) - 1) / (x - 1)

答案 3 :(得分:1)

使用几何级数理论。其中

sum = (first-term(pow(common-ratio,number-of-terms)-1))/(common-ratio-1);
here first-term is obviously 1;
Common-ratio= number itself;
number-of-terms=number+1;

但普通比率应大于1; 对于

Common-ratio=1;
Sum=number*number-of-terms.

答案 4 :(得分:1)

您可以直接评估总和,而无需使用几何级数公式。这样做的优点是不需要除法(例如,如果你想调整代码以返回模数大的数字,那么这是必要的。)

让S(k)为和x ^ 0 + ... + x ^ {k-1},它满足这些递归关系:

S(1)    = 1
S(2n)   = S(n) * (1 + x^n)
S(2n+1) = S(n) * (1 + x^n) + x^{2n}

使用这些,唯一的困难是安排将xp的运行值保持为x ^ n。否则,该算法非常类似于通过平方的自下而上的求幂实现。

#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>

int64_t exponent_sum(int64_t x, int64_t k) {
    int64_t r = 0, xp = 1;
    for (int i = 63; i >= 0; i--) {
        r *= 1 + xp;
        xp *= xp;
        if (((k + 1) >> i) & 1) {
            r += xp;
            xp *= x;
        }
    }
    return r;
}

int main(int argc, char *argv[]) {
    for (int k = 0; k < 10; k++) {
        printf("4^0 + 4^1 + ... + 4^%d = %" PRId64 "\n", k, exponent_sum(4, k));
    }
    return 0;
}