Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
What is Modular Multiplicative Inverse?
3.
Brute Force Approach
3.1.
Pseudocode
3.2.
Code in C++
3.3.
Output
3.4.
Time Complexity
3.5.
Space Complexity
4.
Optimized Extended-Euclidean Algorithm Approach
4.1.
Pseudocode
4.2.
Code in C++
4.3.
Output
4.4.
Time Complexity
4.5.
Space Complexity
5.
Case-Specific Euler's Theorem Approach
5.1.
Pseudocode
5.2.
Code in C++
5.3.
Output
5.4.
Time Complexity
5.5.
Space Complexity
6.
Frequently Asked Questions
6.1.
What is Modular Multiplicative Inverse?
6.2.
How do you find the modular multiplicative inverse?
6.3.
What is an example of modular inverse?
6.4.
What is the multiplicative inverse of 3 modulo 7?
6.5.
What is the multiplicative inverse of 2 mod 7?
7.
Conclusion
Last Updated: Sep 1, 2024
Easy

Modular Multiplicative Inverse

Author SHIKHAR SONI
0 upvote
Modular Multiplicative Inverse

Introduction

The following article introduces Modular Multiplicative Inverse. We will discuss various approaches for finding the modular multiplicative inverse, starting with the brute force approach. Then, we will improve and discuss the optimal approach, along with an alternate approach that can be used easily when we are calculating modular inverse 'a (mod m)' where m is a prime number (you'll notice that this is the case in most such problems that you encounter), or we can easily calculate the Euler's totient function for it.

What is Modular Multiplicative Inverse?

The modular multiplicative inverse of a (mod m) is the number x, such ax ≡ 1 mod(m) (this essentially means m | ax - 1 (read as, `m divides a*x - 1`) or ax % m = 1 (read as, `a*x modulus m equals to 1`)). The modular inverse only exists if a and m are co-prime, i.e., they don't have any common factor other than 1. x is an integer that must also lie in the range [1, m-1].

For example,

a=10, m=499

gcd(a, m) = 1, so the inverse exists.

=> (a * x) % m = 1

=> (10 * 50) % 499 = 1

Hence, x = 50.

Also see, Euclid GCD Algorithm

Brute Force Approach

We'll check for all numbers in the range [1, m-1] for a possible candidate that satisfies the equation ax % m = 1 and returns it. If no such candidate exists, we can conclude that a and m have a common factor and thus, there doesn't exist a valid modular multiplicative inverse, and we return -1.

Pseudocode

func brute(a, m):
	for all i from 1 to m - 1:
		if (a * i) % m == 1:
			return i
	return -1
	
brute(10, 499)

Code in C++

#include <bits/stdc++.h>
using namespace std;

// uncomment if needed
// #define int long long

int modular_multiplicative_inverse(int a, int MOD = 1e9 + 7){
    
    a = a % MOD;
    for(int i = 1; i <= MOD-1; i++){
        if((a * i) % MOD == 1){
            return i;
        }
    }
    return -1;
}

int32_t main(){
    int a = 10, MOD = 499;
    cout << modular_multiplicative_inverse(a, MOD);
}

Output

50

Time Complexity

O(m) time is consumed, as we loop and check the condition (ax % m == 1) for all m-1 possible candidates.

Space Complexity

O(1) extra space is consumed by the algorithm.

Optimized Extended-Euclidean Algorithm Approach

We can use the extended euclidean algorithm (if this topic is new for you, refer to the article here) to find the modular multiplicative inverse. We can use the below observations to arrive at the use of the extended euclidean algorithm in this case.

=> ax % m = 1

=> ax = 1 + mz, here z is a positive integer

=> ax - mz = 1

=> ax + my = 1, replace y = -z

We observe that, extended euclidean algorithm can find x, y, gcd(a, m) in the below equation

=> ax + my = gcd(a, m)

Also, notice that for modular multiplicative inverse to exist, the gcd(a, m) must be 1.

Hence, we can directly use the extended euclidean algorithm, and the x value obtained will be the modular multiplicative inverse of 'a (mod m)'.

The steps followed in the code:

  1. We pass a and m into the extended euclidean algorithm function.
  2. We obtain a gcd and associated values of x and y.
  3. If the gcd is 1, we handle the case when x is negative (adding m to it and finding its modulus with m, adding m and taking modulus with m doesn't affect the result) and return x as the modular inverse.
  4. If the gcd is not 1, we conclude there's no valid modular multiplicative inverse and return -1.
  5. We print the result returned in either step 3 or 4.

Pseudocode

func extended_euc(a, b):
	if a equals 0: 
		return (b, 0, 1)
	[d, x1, y1] = extended_euc(b % a, a)
	y = y1 - x1 * (b / a)
	x = x1
	return d, x, y

[gcd, x, y] = extended_euc(10, 499)
if gcd equals 1:
	x = (x % m + m) % m
	print(x)
else:
	print(-1)

Code in C++

#include <bits/stdc++.h>
using namespace std;

// uncomment if needed
// #define int long long

int extended_euclidean(int a, int b, int& x, int& y) {
    if (!a) {
        // if a is 0, return
        x = 0, y = 1;
        return b;
    }
    int x1, y1;
    int d = extended_euclidean(b % a, a, x1, y1);
    x = y1 - x1 * (b / a);
    y = x1;
    return d;
}

int modular_multiplicative_inverse(int a, int m){
    int x, y;
    int gcd_a_and_m = extended_euclidean(a, m, x, y);
    
    // if the gcd is 1, the multiplicative modular inverse exists
    if(gcd_a_and_m == 1){
        // handle the case when x < 0
        x = (x % m + m) % m;
        return x;
    }
    return -1;
}

int32_t main(){
    int a = 10, MOD = 499;
    cout << modular_multiplicative_inverse(a, MOD);
}

Output

50

Time Complexity

The algorithm takes O(log2(m)) time, same as the extended euclidean algorithm for any given input.

Space Complexity

O(1) extra space is needed, but O(log2(m)) stack memory is consumed due to recursion.

Case-Specific Euler's Theorem Approach

Euler's theorem states that aphi(m) ≡ 1(mod m) (here, phi(m) is the Euler's totient function). In the special case when m is prime, Euler's totient function phi(m)=m-1, and Euler's theorem becomes the popularly known Fermat's little theorem, am-1 ≡ 1(mod m).

We can rearrange the equations to obtain the below,

aphi(m)-1 ≡ a-1 (mod m), Here a-1 is the modular multiplicative inverse.

Or, in the special case when m is prime, we obtain am-2 ≡ a-1 (mod m).

We'll cover the code for when m is a prime number, as it's harder and time-consuming to calculate the Euler's totient function for a more generalised m.

In the code, we only have one step, where we calculate (am-2) % m using modular exponentiation when m is prime.

Pseudocode

// returns a^b mod(MOD) (a to the power b mod MOD)
func modular_exponentiation(a, b, MOD)
	ans = 1
	a = a mod(MOD)
	while b is more than 0
		if b is an odd number
			ans = (ans * a) mod(MOD)
		a = (a * a) mod(MOD)
		b = b / 2
	return ans

// it’s assumed that input m is a prime number
print(modular_exponentiation(a, m-2, m))

Code in C++

#include <bits/stdc++.h>
using namespace std;

// uncomment if needed
// #define int long long

int modular_exponentiation(int a, int b, int MOD = 1e9 + 7){
    int ans = 1;
    a = a % MOD;
    while(b > 0){
        if(b % 2 == 1){
            ans = (ans * a) % MOD;
        }
        a = (a * a) % MOD;
        b = b / 2;
    }
    return ans;
}

int modular_multiplicative_inverse(int a, int m){
    return modular_exponentiation(a, m-2, m);
}

int32_t main(){
    int a = 10, MOD = 499;
    cout << modular_multiplicative_inverse(a, MOD);
}

Output

50

Time Complexity

O(log2(m)) time is taken by this algorithm when m is prime, similar to the extended euclidean algorithm solution. However, this method can be easily used with modular exponentiation and is slightly easier and faster to code iteratively in various circumstances (such as an interview or a contest).

Space Complexity

The algorithm consumes O(1) extra space.

Frequently Asked Questions

What is Modular Multiplicative Inverse?

The modular multiplicative inverse of a (mod m) is the number x, such ax ≡ 1 mod(m) (this essentially means m | ax - 1 (read as, `m divides a*x - 1`) or ax % m = 1. The modular inverse only exists if a and m are co-prime.

How do you find the modular multiplicative inverse?

The modular multiplicative inverse of a number is A X ≅ 1 (mod M). To find the modular multiplicative of a number, we put the values in the above formula. The value of X should fall in the range of 1, 2,... M-1.

What is an example of modular inverse?

An example of modular inverse includes: suppose the value of a is 3 and m is 7. Here a is an integer, and m is a positive integer. The x number that makes a * x mod m = 1 is the modular inverse of A mod C. In the example, the value of x will be 5. Because taking other values will not satisfy the modular value. 

What is the multiplicative inverse of 3 modulo 7?

a=3 and m=7, a is an integer, and m is a positive integer. gcd(3,7)= 1, the inverse exists.
(a*x) % m=1, x is an integer that lies in the range [1, m-1]
3*5 % 7=1 , 5 is the value for which the mod comes 1. Taking other values like 1,2,3,4.....will not satisfy the conditions.  For example, if we take x as 1, the value will be 3, which is not the required answer. So, the answer is 5.

What is the multiplicative inverse of 2 mod 7?

a=2 and m=7, a is an integer, and m is a positive integer. gcd(2,7)= 1, the inverse exists.
(a*x) % m=1, x is an integer that lies in the range [1, m-1]
2*4 % 7=1, 4 is the value for which the mod comes 1. Taking other values like 1,2,3,5.....will not satisfy the conditions.  For example, if we take x as 2, the value will be 4, which is not the required answer. So, the answer is 4.

Conclusion

This article teaches about modular multiplicative inverse and familiarizes you with the idea. We covered various approaches that hope to help you when you encounter a real scenario where you may need to use it to solve a problem quickly. You must check out  Number Theory which covers all the concepts on number theory you need to know to ace problem-solving.

Learn more about the C++ STL library if you have trouble understanding some part of the code. Visit the link here for carefully crafted courses on campus placement and interview preparation on coding ninjas.

Happy learning!

Live masterclass