0

I need to calculate power of a power. For example: 3^2^n . You can think n as input but this example is not the same thing as 9^n. I write a algorithm using loops but now I need to write recursive one. I couldn't find an efficient way to write it.

acalgan
  • 81
  • 9

4 Answers4

2

Let's say x^(y^n) = powpow(x, y, n) with y and n >= 1

If y > 1 and n > 1, powpow(x, y, n) = powpow(x, y, 1) * powpow(x, y, n-1) (getting closer to the result)

If y > 1 and n = 1, powpow(x, y, 1) = x * powpow(x, y-1, 1) (getting closer)

If y = 1 and n = 1, powpow(x, 1, 1) = x (solved)

That's less efficient than a loop, but it's recursive. Is that what you're aiming for ...?

EDIT as @pjs has pointed out, the first case should be: powpow(x, y, 1) = powpow(x, powpow(y, n, 1), 1)

Ilya
  • 5,377
  • 2
  • 18
  • 33
  • 1
    The `y > 1 && n >1` case expressed mathematically is `x^y * x^(y^(n-1))`, which equates to `x^(y + y^(n-1))` rather than the desired outcome `x^(y * y^(n-1))`. – pjs Mar 29 '16 at 22:23
2

I went ahead and implemented this in Ruby, which is pretty darn close to pseudocode and has the added benefit of being testable. Since Ruby also has arbitrary precision integer arithmetic, the following code works with non-trivial arguments.

This implementation is based on the old trick of squaring the base and raising it to half the specified power when the exponent is even, so the recursive stack grows logarithmically rather than linearly in powers. This was inspired by Ilya's answer, but I found that the y > 1 and n > 1 case is not correct, leading me to use the recursive call within a recursive call implemented in the elif n > 1 line below:

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

I was able to confirm that result directly:

irb(main):001:0> 2**5
=> 32
irb(main):002:0> 3**32
=> 1853020188851841
pjs
  • 18,696
  • 4
  • 27
  • 56
0
public class Power {
    int ans = 1;
    int z = 1;
    int x = 1;

    int pow1(int b, int c) {
        if (c > 1) {
            pow1(b, c - 1);
        }
        ans = ans * b;
        return ans;
    }

    void pow(int a, int b, int c) {
        x = pow1(b, c);
        ans = a;
        pow1(a, x - 1);
    }

    public static void main(String[] args) {
        Power p = new Power();
        p.pow(3, 2, 3);
        System.out.println(p.ans);
    }
}
Kostya Shkryob
  • 2,344
  • 17
  • 24
  • It's also a good idea to add a few lines of description to your answer. Why have you chosen this algorithm, what are pros and cons of it, etc. – Kostya Shkryob Mar 29 '16 at 18:26
  • For the question as (x^(y^n)), I tried to implement recursion for (y^n) first and then used the answer of val=(y^n) to again implement recursion for (x^val). – user6130876 Mar 29 '16 at 18:33
0

Reccursive Approach

We can compute power(x, y) efficiently in complexity O(log y) using the following reccurnce :

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

Using master theorem we can compute the complexity of above procedure to be O(log y) (Similar case as that of binary search.)

Now, if we use the above procedure to compute 3 ^ (2 ^ n).

We can see that (2 ^ n) will be computed in O(log n) and 3 ^ k. Where k = 2 ^ n, will be computed in O(log k) = O(log (2 ^ n)) = O(n).

So using the binary exponentiation trick sequentially we can solve this using a complexity of O(n).

Iterative approach

Idea : Suppose we have calculated 3 ^ (2 ^ x). Then we can easily calculated 3 ^ (2 ^ (x + 1)) by just squaring 3 ^ (2 ^ x) as :

( 3 ^ (2 ^ x) ) * ( 3 ^ (2 ^ x) ) =  3 ^ ( (2 ^ x) + (2 ^ x) )
                                  =  3 ^ ( 2 * (2 ^ x) )
                                  =  3 ^ ( (2 ^ (x + 1) )

So, if we start with 3 ^ (2 ^ 0), in n steps we can reach on to 3 ^ (2 ^ n) :

def solve(n):
    ans = 3 ^ (2 ^ 0) = 3
    for i in range(0, n) :
        ans = square(ans)
    return ans

Clearly the complexity of the above solution is also O(n).

Ayush Mishra
  • 506
  • 1
  • 4
  • 15