Algorithm 幂次幂的递推算法

Algorithm 幂次幂的递推算法,algorithm,recursion,pseudocode,Algorithm,Recursion,Pseudocode,我需要计算一个幂的幂。例如:3^2^n。您可以将n视为输入,但此示例与9^n不同。我使用循环编写算法,但现在我需要编写递归算法。我找不到一个有效的方法来写它。假设x^(y^n)=pow(x,y,n)带y和n>=1 如果y>1且n>1,pow(x,y,n)=pow(x,y,1)*pow(x,y,n-1)(更接近结果) 如果y>1且n=1,pow(x,y,1)=x*pow(x,y-1,1)(越来越近) 如果y=1,n=1,pow(x,1,1)=x(已解决) 这比循环效率低,但它是递归的。这就是你的目

我需要计算一个幂的幂。例如:3^2^n。您可以将n视为输入,但此示例与9^n不同。我使用循环编写算法,但现在我需要编写递归算法。我找不到一个有效的方法来写它。

假设x^(y^n)=
pow(x,y,n)
带y和n>=1

如果y>1且n>1,
pow(x,y,n)=pow(x,y,1)*pow(x,y,n-1)
(更接近结果)

如果y>1且n=1,
pow(x,y,1)=x*pow(x,y-1,1)
(越来越近)

如果y=1,n=1,
pow(x,1,1)=x
(已解决)

这比循环效率低,但它是递归的。这就是你的目标吗

编辑正如@pjs所指出的,第一种情况应该是:
powpow(x,y,1)=powpow(x,powpow(y,n,1)
假设x^(y^n)=
powpow(x,y,n)
,其中y和n>=1

如果y>1且n>1,
pow(x,y,n)=pow(x,y,1)*pow(x,y,n-1)
(更接近结果)

如果y>1且n=1,
pow(x,y,1)=x*pow(x,y-1,1)
(越来越近)

如果y=1,n=1,
pow(x,1,1)=x
(已解决)

这比循环效率低,但它是递归的。这就是你的目标吗

编辑正如@pjs所指出的,第一种情况应该是:
powpow(x,y,1)=powpow(x,powpow(y,n,1),1)

我们可以使用以下公式有效地计算复杂度为O(logy)的功率(x,y):

power(x, y) : 
   if y is 0 : return 1

   if y is even :
       return square( power(x, y / 2))
   else :
       return square( power(x, (y - 1) / 2 ) * x
使用我们可以计算上述过程的复杂度为O(logy)(类似于二进制搜索的情况)

现在,如果我们使用上面的过程来计算3^(2^n)

我们可以看到,(2^n)将以O(logn)和3^k计算。其中k=2^n,将以O(log k)=O(log(2^n))=O(n)的形式计算

因此,按顺序使用二进制幂运算技巧,我们可以使用O(n)的复杂度来解决这个问题

迭代方法

想法:假设我们计算了3^(2^x)。然后我们可以很容易地计算出3^(2^(x+1)),只需将3^(2^x)平方为:

因此,如果我们从3^(2^0)开始,在n个步骤中,我们可以达到3^(2^n):


显然,上述解决方案的复杂性也是O(n)
重新草书方法

我们可以使用以下公式有效地计算复杂度为O(logy)的功率(x,y):

power(x, y) : 
   if y is 0 : return 1

   if y is even :
       return square( power(x, y / 2))
   else :
       return square( power(x, (y - 1) / 2 ) * x
使用我们可以计算上述过程的复杂度为O(logy)(类似于二进制搜索的情况)

现在,如果我们使用上面的过程来计算3^(2^n)

我们可以看到,(2^n)将以O(logn)和3^k计算。其中k=2^n,将以O(log k)=O(log(2^n))=O(n)的形式计算

因此,按顺序使用二进制幂运算技巧,我们可以使用O(n)的复杂度来解决这个问题

迭代方法

想法:假设我们计算了3^(2^x)。然后我们可以很容易地计算出3^(2^(x+1)),只需将3^(2^x)平方为:

因此,如果我们从3^(2^0)开始,在n个步骤中,我们可以达到3^(2^n):


显然,上述解决方案的复杂性也是O(n)

我在Ruby中实现了这一点,它非常接近伪代码,并且具有可测试性的额外好处。由于Ruby还具有任意精度的整数算法,下面的代码可以处理非平凡参数

此实现基于一个老技巧,即当指数为偶数时,将基数平方并将其提高到指定幂的一半,因此递归堆栈以对数而不是线性幂增长。这是从Ilya的回答中得到的启发,但我发现
y>1和n>1
的情况不正确,导致我在下面的
elif n>1
行中实现的递归调用中使用递归调用:

def powpow(x, y, n)
  if y == 0
    return 1
  elsif y == 1 || n == 0
    return x
  elsif n > 1
    return powpow(x, powpow(y, n, 1), 1)
  elsif y.even?
    return powpow(x * x, y / 2, 1)
  else
    return x * powpow(x * x, y / 2, 1)
  end
end

p powpow(3,2,5)   # => 1853020188851841
我能够直接确认这一结果:

irb(main):001:0> 2**5
=> 32
irb(main):002:0> 3**32
=> 1853020188851841

我继续用Ruby实现了它,它非常接近于伪代码,并且具有可测试性的额外好处。由于Ruby还具有任意精度的整数算法,下面的代码可以处理非平凡参数

此实现基于一个老技巧,即当指数为偶数时,将基数平方并将其提高到指定幂的一半,因此递归堆栈以对数而不是线性幂增长。这是从Ilya的回答中得到的启发,但我发现
y>1和n>1
的情况不正确,导致我在下面的
elif n>1
行中实现的递归调用中使用递归调用:

def powpow(x, y, n)
  if y == 0
    return 1
  elsif y == 1 || n == 0
    return x
  elsif n > 1
    return powpow(x, powpow(y, n, 1), 1)
  elsif y.even?
    return powpow(x * x, y / 2, 1)
  else
    return x * powpow(x * x, y / 2, 1)
  end
end

p powpow(3,2,5)   # => 1853020188851841
我能够直接确认这一结果:

irb(main):001:0> 2**5
=> 32
irb(main):002:0> 3**32
=> 1853020188851841

n
总是一个正整数吗?是的,这是一个正整数,你能证明一下吗?我们不能做9^n。我们能做3^(2n)吗?澄清一下:你想评估3^(2n)?你被困在哪里?你能添加你的初始试用期吗,即使它偏离了方向吗?
n
是否总是一个正整数?是的,它是一个正整数,请你确认一下?我们不能做9^n。我们能做3^(2n)吗?澄清一下:你想评估3^(2n)?你被困在哪里?你能添加你的初始试用期吗,即使它偏离了方向?在你的答案中添加几行描述也是一个好主意。你为什么选择这个算法,它的优缺点是什么,等等。对于问题(x^(y^n)),我首先尝试实现(y^n)的递归,然后使用val=(y^n)的答案再次实现(x^val)的递归。在你的答案中添加几行描述也是一个好主意。你为什么选择这个算法,它的优点和缺点是什么,等等。对于问题(x^(y^n)),我首先尝试实现(y^n)的递归,然后使用val=(y^n)的答案再次实现(x^val)的递归