# Using Chinese Remainder Theorem to Combine Modular equations

Given N modular equations: **A â‰… x _{1}mod(m_{1})** . .

**A â‰… x**Find x in the equation

_{n}mod(m_{n})**A â‰… xmod(m**where m

_{1}*m_{2}*m_{3}..*m_{n})_{i}is prime, or a power of a prime, and i takes values from 1 to n. The input is given as two arrays, the first being an array containing values of each x

_{i}, and the second array containing the set of values of each prime. m

_{i}Output an integer for the value of x in the final equation.

**Examples :**

Consider the two equations A â‰… 2mod(3) A â‰… 3mod(5)Input :2 3 3 5Output :8 Consider the four equations, A â‰… 3mod(4) A â‰… 4mod(7) A â‰… 1mod(9) (3^{2}) A â‰… 0mod(11)Input :3 4 1 0 4 7 9 11Output :1243

**Explanation :** We aim to solve these equations two at a time. We take the first two equations, combine it, and use that result to combine with the third equation, and so on. The process of combining two equations is explained as follows, by taking example 2 for reference:

- A â‰… 3mod(4) and A â‰… 4mod(7) are the two equations that we are provided with at first. Let the resulting equation be some A
_{0}â‰… x_{0}mod(m_{1}* m_{2}).- A
_{0}is given by m_{1}‘ * m_{1}* x_{0}+ m_{0}‘ * m_{0}* x_{1}where m_{1}‘ = modular inverse of m_{1}modulo m_{0}and m_{0}‘ = modular inverse of m_{0}modulo m_{1} - We can calculate modular inverse using extended euclidean algorithm.
- We find x
_{0}to be A_{0}mod (m_{1}* m_{2}) - We get our new equation to be A â‰… 11mod(28), where A is 95

- A
- We now try to combine this with equation 3, and by a similar method, we get A â‰… 235mod(252), where A = 2503
- And finally, on combining this with equation 4, we get A â‰… 1243mod(2772) where A = 59455 and x = 1243

We observe that 2772 is rightly equal to 4 * 7 * 9 * 11. We have thus found the value of x for the final equation. You can refer to Extended Euclidean Algorithm and Modular multiplicative inverse for extra information on these topics.

## C++

`// C++ program to combine modular equations` `// using Chinese Remainder Theorem` `#include<bits/stdc++.h>` `using` `namespace` `std;` `// function that implements Extended euclidean` `// algorithm` `vector<` `int` `> extended_euclidean(` `int` `a,` `int` `b){` ` ` `if` `(a == 0){` ` ` `vector<` `int` `> temp;` ` ` `temp.push_back(b);` ` ` `temp.push_back(0);` ` ` `temp.push_back(1);` ` ` `return` `temp;` ` ` `}` ` ` `else` `{` ` ` `vector<` `int` `> temp(3);` ` ` `temp= extended_euclidean(b % a, a);` ` ` `int` `g = temp[0];` ` ` `int` `y = temp[1];` ` ` `int` `x = temp[2];` ` ` `temp[0] = g;` ` ` `temp[1] = x - ((b/a) * y);` ` ` `temp[2] = y;` ` ` `return` `temp;` ` ` `}` ` ` `vector<` `int` `> temp;` ` ` `return` `temp;` `}` `// modular inverse driver function` `int` `modinv(` `int` `a,` `int` `m){` ` ` `vector<` `int` `> temp(3);` ` ` `temp = extended_euclidean(a, m);` ` ` `int` `g = temp[0];` ` ` `int` `x = temp[1];` ` ` `int` `y = temp[2];` ` ` ` ` `// Since we are taking the modulo of` ` ` `// negative numbers so, to have positive` ` ` `// output of the modulo we use this formula.` ` ` `int` `ans = x - (` `floor` `(x/(` `float` `)m) * m);` ` ` `return` `ans;` `}` ` ` `// function implementing Chinese remainder theorem` `// list m contains all the modulii` `// list x contains the remainders of the equations` `int` `crt(vector<` `int` `> &m,vector<` `int` `> & x)` `{` ` ` ` ` `// We run this loop while the list of` ` ` `// remainders has length greater than 1` ` ` `while` `(1)` ` ` `{` ` ` ` ` `// temp1 will contain the new value` ` ` `// of A. which is calculated according` ` ` `// to the equation m1' * m1 * x0 + m0'` ` ` `// * m0 * x1` ` ` `int` `var1 = (modinv(m[1],m[0]));` ` ` `int` `var2 = (modinv(m[0],m[1]) );` ` ` `// cout << var1 << " " << var2 << endl;` ` ` `int` `temp1 = (modinv(m[1],m[0])) * x[0] * m[1] + (modinv(m[0],m[1]) )* x[1] * m[0];` ` ` `// temp2 contains the value of the modulus` ` ` `// in the new equation, which will be the` ` ` `// product of the modulii of the two` ` ` `// equations that we are combining` ` ` `int` `temp2 = m[0] * m[1];` ` ` `// cout << temp1<< " "<<temp2<< endl;` ` ` `// we then remove the first two elements` ` ` `// from the list of remainders, and replace` ` ` `// it with the remainder value, which will` ` ` `// be temp1 % temp2` ` ` `x.erase(x.begin());` ` ` `x.erase(x.begin());` ` ` `x.insert(x.begin(), temp1%temp2);` ` ` `//we then remove the first two values from` ` ` `//the list of modulii as we no longer require` ` ` `// them and simply replace them with the new` ` ` `// modulii that we calculated` ` ` `m.erase(m.begin());` ` ` `m.erase(m.begin());` ` ` `m.insert(m.begin(), temp2);` ` ` `// once the list has only one element left,` ` ` `// we can break as it will only contain` ` ` `// the value of our final remainder` ` ` `if` `(x.size()== 1){` ` ` `break` `;` ` ` `}` ` ` `}` ` ` ` ` `// returns the remainder of the final equation` ` ` `return` `x[0];` `}` `// driver segment` `int` `main(){` ` ` `vector<` `int` `> m = {4, 7, 9, 11};` ` ` `vector<` `int` `> x = {3, 4, 1, 0};` ` ` `cout << crt(m, x) << endl;` ` ` `return` `0;` `}` `// The code is contributed by Gautam goel (gautamgoe962)` |

## Python

`# Python 2.x program to combine modular equations` `# using Chinese Remainder Theorem` `# function that implements Extended euclidean` `# algorithm` `def` `extended_euclidean(a, b):` ` ` `if` `a ` `=` `=` `0` `:` ` ` `return` `(b, ` `0` `, ` `1` `)` ` ` `else` `:` ` ` `g, y, x ` `=` `extended_euclidean(b ` `%` `a, a)` ` ` `return` `(g, x ` `-` `(b ` `/` `/` `a) ` `*` `y, y)` `# modular inverse driver function` `def` `modinv(a, m):` ` ` `g, x, y ` `=` `extended_euclidean(a, m)` ` ` `return` `x ` `%` `m` `# function implementing Chinese remainder theorem` `# list m contains all the modulii` `# list x contains the remainders of the equations` `def` `crt(m, x):` ` ` `# We run this loop while the list of` ` ` `# remainders has length greater than 1` ` ` `while` `True` `:` ` ` ` ` `# temp1 will contain the new value` ` ` `# of A. which is calculated according` ` ` `# to the equation m1' * m1 * x0 + m0'` ` ` `# * m0 * x1` ` ` `temp1 ` `=` `modinv(m[` `1` `],m[` `0` `]) ` `*` `x[` `0` `] ` `*` `m[` `1` `] ` `+` `\` ` ` `modinv(m[` `0` `],m[` `1` `]) ` `*` `x[` `1` `] ` `*` `m[` `0` `]` ` ` `# temp2 contains the value of the modulus` ` ` `# in the new equation, which will be the` ` ` `# product of the modulii of the two` ` ` `# equations that we are combining` ` ` `temp2 ` `=` `m[` `0` `] ` `*` `m[` `1` `]` ` ` `# we then remove the first two elements` ` ` `# from the list of remainders, and replace` ` ` `# it with the remainder value, which will` ` ` `# be temp1 % temp2` ` ` `x.remove(x[` `0` `])` ` ` `x.remove(x[` `0` `])` ` ` `x ` `=` `[temp1 ` `%` `temp2] ` `+` `x` ` ` `# we then remove the first two values from` ` ` `# the list of modulii as we no longer require` ` ` `# them and simply replace them with the new` ` ` `# modulii that we calculated` ` ` `m.remove(m[` `0` `])` ` ` `m.remove(m[` `0` `])` ` ` `m ` `=` `[temp2] ` `+` `m` ` ` `# once the list has only one element left,` ` ` `# we can break as it will only contain` ` ` `# the value of our final remainder` ` ` `if` `len` `(x) ` `=` `=` `1` `:` ` ` `break` ` ` `# returns the remainder of the final equation` ` ` `return` `x[` `0` `]` `# driver segment` `m ` `=` `[` `4` `, ` `7` `, ` `9` `, ` `11` `]` `x ` `=` `[` `3` `, ` `4` `, ` `1` `, ` `0` `]` `print` `crt(m, x)` |

## Javascript

`// JavaScript program to combine modular equations` `// using Chinese Remainder Theorem` `// function that implements Extended euclidean` `// algorithm` `function` `extended_euclidean(a, b){` ` ` `if` `(a == 0){` ` ` `let temp = [b, 0, 1];` ` ` `return` `temp;` ` ` `}` ` ` `else` `{` ` ` `let temp= extended_euclidean(b % a, a);` ` ` `let g = temp[0];` ` ` `let y = temp[1];` ` ` `let x = temp[2];` ` ` `temp[0] = g;` ` ` `temp[1] = x - (Math.floor(b/a) * y);` ` ` `temp[2] = y;` ` ` `return` `temp;` ` ` `}` ` ` `let temp;` ` ` `return` `temp;` `}` `// modular inverse driver function` `function` `modinv(a, m){` ` ` `let temp = extended_euclidean(a, m);` ` ` `let g = temp[0];` ` ` `let x = temp[1];` ` ` `let y = temp[2];` ` ` ` ` `// Since we are taking the modulo of` ` ` `// negative numbers so, to have positive` ` ` `// output of the modulo we use this formula.` ` ` `let ans = x - (Math.floor(x/m) * m);` ` ` `return` `ans;` `}` ` ` `// function implementing Chinese remainder theorem` `// list m contains all the modulii` `// list x contains the remainders of the equations` `function` `crt(m, x)` `{` ` ` ` ` `// We run this loop while the list of` ` ` `// remainders has length greater than 1` ` ` `while` `(1)` ` ` `{` ` ` ` ` `// temp1 will contain the new value` ` ` `// of A. which is calculated according` ` ` `// to the equation m1' * m1 * x0 + m0'` ` ` `// * m0 * x1` ` ` `let var1 = (modinv(m[1],m[0]));` ` ` `let var2 = (modinv(m[0],m[1]) );` ` ` `// cout << var1 << " " << var2 << endl;` ` ` `let temp1 = (modinv(m[1],m[0])) * x[0] * m[1] + (modinv(m[0],m[1]) )* x[1] * m[0];` ` ` `// temp2 contains the value of the modulus` ` ` `// in the new equation, which will be the` ` ` `// product of the modulii of the two` ` ` `// equations that we are combining` ` ` `let temp2 = m[0] * m[1];` ` ` `// cout << temp1<< " "<<temp2<< endl;` ` ` `// we then remove the first two elements` ` ` `// from the list of remainders, and replace` ` ` `// it with the remainder value, which will` ` ` `// be temp1 % temp2` ` ` `x.shift();` ` ` `x.shift();` ` ` `x.unshift(temp1 % temp2);` ` ` `//we then remove the first two values from` ` ` `//the list of modulii as we no longer require` ` ` `// them and simply replace them with the new` ` ` `// modulii that we calculated` ` ` `m.shift();` ` ` `m.shift();` ` ` `m.unshift(temp2);` ` ` `// once the list has only one element left,` ` ` `// we can break as it will only contain` ` ` `// the value of our final remainder` ` ` `if` `(x.length== 1){` ` ` `break` `;` ` ` `}` ` ` `}` ` ` ` ` `// returns the remainder of the final equation` ` ` `return` `x[0];` `}` `// driver segment` `let m = [4, 7, 9, 11];` `let x = [3, 4, 1, 0];` `console.log(crt(m, x));` `// The code is contributed by phasing17` |

Output1243

**Time Complexity :** O(l) ,where l is the size of remainder list.

**Space Complexity :** O(1) ,as we are not using any extra space.

This theorem and algorithm has excellent applications. One very useful application is in calculating ^{n}C_{r} % m where m is not a prime number, and Lucas Theorem cannot be directly applied. In such a case, we can calculate the prime factors of m, and use the prime factors one by one as a modulus in our ^{n}C_{r} % m equation which we can calculate using Lucas Theorem, and then combine the resulting equations together using the above shown Chinese Remainder Theorem. This article is contributed by **Deepak Srivatsav**. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.