如何仅使用恒定时间的算术运算来计算指数?

问题描述

我正在尝试寻找一种方法来遍历大小为N的整数数组,并将每个整数乘以128 ^((N-1)-i),其中N是数组的长度,而i是是整数的索引,然后将所有结果加在一起。

例如,[1、2、3、4]的数组输入将返回1 *(128 ^ 3)+ 2 *(128 ^ 2)+ 3 *(128 ^ 1)+ 4 *(128 ^ 0)。

我的算法需要在O(N)时间内运行,但是指数运算非常昂贵,例如2 ^ 3需要进行三个运算。因此,我需要找到一种仅使用算术运算(-,+,*,/,%)在O(1)时间内对数组中的每个整数进行运算的方法。我能想到的最明显(错误)的方法就是简单地将每个整数(N-i)相乘,但这并不需要花费固定的时间。我还考虑过通过平方来使用幂运算,但是对每个整数进行运算都需要log_2(N-i)时间,这不是常数。

解决方法

128是2 ^ 7,将数字乘以128 ^ k会将其二进制表示左移7 * k个位置。

1 * (128^3) + 2 * (128^2) + 3 * (128^1) + 4 * (128^0)
= 1000000000000000000000 + 1000000000000000 + 110000000 + 100 
,

要回答标题问题:有可能证明那些操作数不变,就不能使数字足够大以容纳足够大的指数。

要回答一个基本问题:您可以使用有时归因于Horner的多项式求值方法:((1 * 128 + 2) * 128 + 3) * 128 + 4。请注意,除非您要进行修改,否则操作bignum仍将花费Õ(n 2 )时间。

如果您确实在使用bignums,则存在一个更复杂的分治法,假设bignum乘法比school方法运行得更快,则应该更快。想法是将输入分成两半,使用递归分别评估下半部分和上半部分,然后将它们放在一起。在您的示例中,这看起来像

(1 * 128 + 2) * 128^2 + (3 * 128 + 4),

我们通过重复平方来计算项128^2(即128^(n/2))。由于我们有重复发生,因此操作计数仍为O(n)

T(n) = 2 T(n/2) + O(log n),

属于Case 1。在实践中,运行时间将由较大的乘法决定,而特定实现的渐近复杂度则为