Sourabh Khandelwal
Sourabh Khandelwal

Reputation: 129

C++ : How to calculate modulo of a number raised to large power?

I am solving a programming problem where I have to print the answer in the format answer mod 10 ^ 9 + 7, where 'answer' is the actual answer to the problem.

I have figured out the algorithm to solve the problem, however the caveat is that the answer to the problem is always of the format m * 10 ^ n, where

1 <= m <= 8 and 2 <= n <= 10 ^ 18, that is in the answer 10 can be raised to a power as large as 10 ^ 18. Ofcourse, directly calculating 10 ^ n may overflow.

What should I do next?

Upvotes: 0

Views: 4043

Answers (1)

vishal-wadhwa
vishal-wadhwa

Reputation: 1031

Evaluating 10^n mod M:

What you need is Modular Exponentiation. It can compute (a^b)%m in log_2(b)(log base 2).

Example

Let's say you need to compute 10^9.

  1. One way is you sequentially multiple 10, 9 times.
  2. Or, use divide and conquer approach.

    10^9 = (10^8)*(10^1)

    10^8 = (10^4)*(10^4) : Do you need to compute 10^4 twice?

    10^4 = (10^2)*(10^2) : Do you need to compute 10^2 twice?

    10^2 = (10^1)*(10^1)

    10^1 = (10^1)*(10^0)

    10^0 is the base case.

    So, what we basically do is:

    1. If power is an odd number, then we compute base^(power-1) and multiply it with base to get base^power. [base^power = (base^(power-1)) * base)]
    2. If power is an even number, then we compute base^(power/2) and multiply it with itself to get base^power. [base^power = (base^(power/2)) * (base^(power/2))]. But we compute base^(power/2) only once.

Computational Complexity:

As stated here:

A brief analysis shows that such an algorithm uses floor(log_2(n)) squarings and at most floor(log_2(n)) multiplications. More precisely, the number of multiplications is one less than the number of ones present in the binary expansion of n.

So, we can say that the runtime is of the order of log_2(n). (O(log_2(power)))

Evaluating the modulo part:

It is easy to notice that while computing a value as large as 10^(10^18), we are bound to overflow even largest of the primitive types (long long int). And here enters the Modular Multiplication, according to which (a * b) % c = ((a % c) * (b % c)) % c. As a side note, you might not see this rule in use when you directly look at code, but it is being used if you evalute the recursive calls.

Problem solved?

We prevent overflow by computing the modulo on the run. Say, if we got some value as 10^9 and we need to multiply it with itself. Overflow? Nah, not this time.

ans = ((10^9 % 1000000007) * (10^9 % 1000000007)) % 1000000007
ans = 10^18 % 1000000007
ans = 49

Code:

While there are multiple implementations, here is a simple one:

const int M = 1e9 + 7;
long long int powxy(long long int x, long long int y) {
    if (y == 0) return 1;
    if (y%2 == 1) return (x*powxy(x, y-1))%M;
    long long int t = powxy(x, y/2);
    return (t*t)%M;
}

Tested here.

Upvotes: 3

Related Questions