Implement 64-bit modular exponentiation safely
Company: Salesforce
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Technical Screen
Quick Answer: This question evaluates proficiency in modular arithmetic, safe 64‑bit integer operations, and algorithmic techniques for overflow‑resistant modular multiplication and exponentiation.
Constraints
- 0 ≤ a < 2^61−1
- 0 ≤ b < 2^61−1
- 1 ≤ m < 2^61−1
- Use only 64-bit operations (or a 128-bit-emulated multiply); no intermediate value may overflow a 64-bit integer in C++/Java
- 0^0 is defined as 1
Examples
Input: (2, 10, 1000)
Expected Output: 24
Explanation: 2^10 = 1024, and 1024 mod 1000 = 24.
Input: (3, 0, 7)
Expected Output: 1
Explanation: Any base to the 0 power is 1, and 1 mod 7 = 1.
Input: (0, 0, 5)
Expected Output: 1
Explanation: 0^0 is defined as 1 by convention; 1 mod 5 = 1.
Input: (5, 117, 19)
Expected Output: 1
Explanation: 19 is prime and 5 is not a multiple of 19, so by Fermat's little theorem 5^18 ≡ 1 (mod 19); 117 = 6·18 + 9... computing directly gives 5^117 mod 19 = 1.
Input: (123456789, 987654321, 1000000007)
Expected Output: 652541198
Explanation: A large exponent against the common prime modulus 1e9+7; square-and-multiply yields 652541198.
Input: (10, 100, 1)
Expected Output: 0
Explanation: Modulus 1: every integer is congruent to 0, so the result is 0 regardless of a and b.
Input: (2305843009213693950, 2, 2305843009213693951)
Expected Output: 1
Explanation: m = 2^61−1. a = m−1 ≡ −1 (mod m), and (−1)^2 = 1. This is the overflow-critical case: a*a ≈ 2^122 would overflow a 64-bit multiply, so a 128-bit or double-and-add mulmod is required to get 1.
Input: (7, 13, 1)
Expected Output: 0
Explanation: Modulus 1 again with a nonzero base/exponent; the answer is still 0.
Hints
- Square-and-multiply: process the exponent bit by bit. Keep `result` and `base`; whenever the current low bit of the exponent is 1, multiply `result` by `base` (mod m); always square `base` (mod m) and shift the exponent right.
- The dangerous step is the multiply (x*y) % m, not the exponentiation loop. When m is near 2^61, x*y is near 2^122 and overflows 64 bits. Use a 128-bit product (unsigned __int128 in C++) or a binary double-and-add mulmod: result += x then x += x, each reduced mod m, which keeps every value below 2*m < 2^62.
- Handle the corner cases first: if m == 1 the answer is 0; reduce a mod m before the loop; b == 0 must yield 1 (the loop naturally leaves result = 1).