Problem overview
Power(int a, int n) returns a raised to the power n, modulo 1337. Both inputs are positive and can be as large as 2^31 - 1. The examples are Power(2, 3) = 8, Power(2, 10) = 1024, Power(1, 1000) = 1 and Power(2147483647, 200) = 1198.
Computing a^n directly is hopeless, since even 2^200 has dozens of digits and no int or long can hold it. Looping n times is also far too slow for an exponent near two billion. The solution needs two ideas: keep every number small with the modulo operator, and cut the exponent in half at every step.
Approach: halve the exponent
When n is even, a^n = a^(n/2) * a^(n/2). So one recursive call for the half-sized exponent is enough, and its result is used twice. When n is odd, a^n = a^(n-1) * a, and n - 1 is even, so the next call takes the halving branch. The exponent at least halves every two calls, so the recursion goes about 2 * log₂ n levels deep. For n near two billion, that is around 62 calls, not billions.
The modulo can be applied at every step, because (x * y) % m equals ((x % m) * (y % m)) % m. Every intermediate result is then below 1337, and a product of two such results is below 1337 * 1337, which fits comfortably in an int.
Here is Power(2, 10) as a chain of calls: Power(2, 10) calls Power(2, 5), which calls Power(2, 4), then Power(2, 2), then Power(2, 1). The base case returns 2, then 2 * 2 = 4, then 4 * 4 = 16, then 16 * 2 = 32, and finally 32 * 32 = 1024. The result 1024 is below 1337, so the modulo leaves it unchanged.
An odd exponent works the same way. For Power(2, 3), the call goes to Power(2, 2), then to Power(2, 1), which returns 2. The even level returns 2 * 2 = 4, and the odd level returns 4 * 2 = 8.
The large example shows how few calls are needed. Power(2147483647, 200) visits only the exponents 200, 100, 50, 25, 24, 12, 6, 3, 2 and 1. That is 10 calls, and the answer is 1198. The exponent 25 is odd, so it passes through 24 before halving again.
Step by step
- Store the modulus in an
intvariablemod, set to1337, so the number has a name. - Base case. If
n == 1, returna % mod. The first power ofaisa, reduced to stay in range. - Check whether
nis even withn % 2 == 0. - Compute the half power. Inside the
if, callPower(a, n / 2)and store it inx. - Square it. Return
(x * x) % mod. Sincexis already below 1337, the product is small. - Handle odd
n. Below theif,nis odd, so return(Power(a, n - 1) * (a % mod)) % mod. Reducingafirst matters, as explained below.
The solution in C#
class Solution {
public int Power(int a, int n) {
int mod = 1337;
if (n == 1) {
return a % mod;
}
if (n % 2 == 0) {
int x = Power(a, n / 2);
return (x * x) % mod;
}
return (Power(a, n - 1) * (a % mod)) % mod;
}
}
C# details worth knowing
intoverflow is silent. C# does not raise an error when anintproduct is too large. It wraps to a wrong value. If the last line multipliedPower(a, n - 1), which can be up to 1336, by the rawa, which can be 2147483647, the product would not fit in anint. Writinga % modfirst keeps both factors below 1337.- Integer division.
n / 2onints drops the fraction, so no cast orMath.Flooris needed. It is only used whennis even, so nothing is lost. - The
%operator. With non-negative operands, as in this problem,%gives the ordinary remainder. In C#, a negative left operand gives a negative or zero result, which is not an issue here. - Naming. The method is
Powerin PascalCase. C# is case-sensitive, so the recursive calls must use the same spelling.
Complexity
The exponent is halved at least every second call, so there are at most about 2 * log₂ n calls, each doing a constant amount of work. The time is O(log n).
Each pending call stays on the call stack until its callee returns, so the extra space is also O(log n).
Edge cases and common mistakes
- Calling
Powertwice for evenn. WritingPower(a, n / 2) * Power(a, n / 2)makes two calls per level and loses the whole saving, givingO(n)calls. Store the result inxand square it. - Forgetting the base case. Without
n == 1, the exponent keeps shrinking forever and the stack overflows. Any call reachingn == 0would recurse without end, since0is even and halves to itself. The lesson promisesn >= 1. - Using the raw
ain a product. A largeatimes a result up to 1336 overflows anint. Reduce witha % modfirst. - Applying the modulo only at the end. The unreduced power would overflow long before the modulo ran.
- Result of 1.
Power(1, 1000)is1because every power of 1 is 1. The trace goes through the odd and even branches several times and still ends at the base case.
Testing
| a | n | result |
|---|---|---|
2 | 3 | 8 |
2 | 10 | 1024 |
1 | 1000 | 1 |
2147483647 | 200 | 1198 |