2

I am trying to solve a problem where we have to output the the last digit of the given number n^p.

int modularExponentiation(int n, long long p, int m){
    if(p == 0) return 1;
    if(p & 1)
        return (n % m * modularExponentiation((n*n) % m, p / 2, m) % m) % m;//line 4
    return modularExponentiation((n*n) % m, p / 2, m) % m;
}

In this recursive code, here we are changing the temporary result by applying modulo in line 4. Will this not bring any change in the final answer? for example if at any intermediary stage the answer is 81^4, applying %10 at 81 and replacing it with 1, will it not change the final result?

2 Answers2

2

No, this does not affect the result, because (a*b)%m == ((a%m) * (b%m))%m. Exponentiation is of course just repeated multiplication, so the same principle applies.

(81^4)%10 is small enough to try this by hand. Go ahead, write it out.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • I am searching for the mathematical term for this equation. Could you help me please?:D – RoQuOTriX Mar 31 '20 at 11:45
  • @RoQuOTriX I don't think anyone has cared about naming that equality. You usually learn it, and how to prove it, when you're learning about modular arithmetic. – molbdnilo Mar 31 '20 at 11:50
  • I thought it has a name, as we discussed it in cryptography. But maybe there is only a name for the encryption method based on the equation – RoQuOTriX Mar 31 '20 at 11:52
  • @MSalters I understand that (a*b)%m == ((a%m) * (b%m))%m. But my problem here is that if b is a small number we use the same algorithm but without the modulo anywhere. But since we are replacing the results with their modulo, wont the final computation of a^b get affected and if the final result does not get affected, can you please mention how we choose the modulo number(m in this case)(consider a%m and a>m). Thanks in advance. – Pranav Venkata Mar 31 '20 at 12:06
  • 1
    @PranavVenkata: The logic is that we can write `a` as `(a/m)*m + (a%m)`, and the same for `b`. Remember that in C++, `a/m` is rounded down. Now `(a/m)*m` obviously is a multiple of `m`, so `((a/m)*m)%m == 0`. So all we have to do is write out `a*b` to get `(a/m*b/m)*m*m + (a/m*b%m+b/m*a%m)*m + (a%m)*(b%m)`. Again, all multiples of `m` are congruent with 0, modulo `m`. – MSalters Mar 31 '20 at 12:12
0

For modular addition and multiplication, you can take a mod at every step and it won't affect the result. In fact, that's how you're supposed to do modular exponentiation to avoid overflows. Therefore, your final function would look like this:

long long modExp(long long n, long long p, long long m) {
    if (p == 0) {
        // m could be 1 you never know
        return 1 % m;
    }
    n %= m;
    return (n * modExp(n, p - 1, m)) % m;
}
Aplet123
  • 33,825
  • 1
  • 29
  • 55
  • let us consider (3^3)%10 which can be written as (3%10*3%10*3%10)%10 which turns out to be 27%10 which is 7. if we replace the base 27 with 7(considering 27 is an intermediate result in the recursion process), will that not give us the wrong result in the solution?. Thank you in advance! – Pranav Venkata Mar 31 '20 at 11:54
  • How do I consider m(modulo) above? – Pranav Venkata Mar 31 '20 at 12:24
  • @PranavVenkata `7 % 10` is also 7. I think you need to read more about modular arithmetic. – molbdnilo Mar 31 '20 at 12:25
  • @PranavVenkata: Modulo 10, 27 and 7 are _congruent_. For compatible operations, you can subsitute congruent numbers. Note that not all operations are compatible. √4 is 2, but √64 = 8. Yet 64%10=4, but 8%10 is not 2. Multiplication is compatible, however. – MSalters Mar 31 '20 at 12:27
  • Addition, subtraction, and multiplication fully work with modular arithmetic. Division does work, there's just some extra steps you have to take. – Aplet123 Mar 31 '20 at 12:28