Given two integers a and n, write a function to compute a^n.

Code

Algorithmic Paradigm: Divide and conquer.

int power(int x, unsigned int y) { 
    if (y == 0) 
        return 1; 
    else if (y%2 == 0) 
        return power(x, y/2)*power(x, y/2); 
    else
        return x*power(x, y/2)*power(x, y/2); 
} 

Time Complexity: O(n) | Space Complexity: O(1)

Optimized Solution: O(logn)

int power(int x, unsigned int y) { 
    int temp; 
    if( y == 0) 
        return 1; 
    temp = power(x, y/2); 
    if (y%2 == 0) 
        return temp*temp; 
    else
        return x*temp*temp; 
} 

Why is this faster?

Suppose we have x = 5, y = 4, we know that our answer is going to be (5 * 5 * 5 * 5).

If we break this down, we notice that we can write (5 * 5 * 5 * 5) as (5 * 5) * 2 and further, we can write (5 * 5) as 5 * 2.

Through this observation, we can optimize our function to O(log n) by calculating power(x, y/2) only once and storing it.

Modular Exponentiation

Given three numbers x, y, and p, compute (x^y) % p

int power(int x, unsigned int y, int p) { 
    int res = 1;  
    x = x % p; 
    while (y > 0) {  
        if (y & 1) 
            res = (res*x) % p; 
  
        // y must be even now 
        y = y >> 1; 
        x = (x*x) % p;   
    } 
    return res; 
} 

Time Complexity: O(Log y).