Open in App
Not now

# Find Square Root under Modulo p | (When p is product of two primes in the form 4*i + 3)

• Last Updated : 16 Jul, 2021

Given an integer N and an integer P denoting the product of two primes, the task is to find all possible Square Root of N under modulo P if it exists. It is given that P is the product of p1 and p2, where p1 and p2 are prime numbers of the form 4i + 3 where i is any integer. Some examples of such prime numbers are (7, 11, 19, 23, 31).
Examples:

Input: N = 67, P = 77
Output: 23 65 12 54
Explanation:
All possible answers are (23, 65, 12, 54)
Input: N = 188, P = 437
Output: 25 44 393 412
Explanation:

All possible answers are (25, 44, 393, 412)

Naive Approach:
The simplest approach to solve this problem is to consider all numbers from 2 to P – 1 and for every number, check if it is the square root of N under modulo P. If found to be true, then print that number and break.
Time Complexity: O(P)
Auxiliary Space: O(1)
Efficient Approach:
To optimize the above approach, the idea is to use Prime Factorization to obtain two factors p1 and p2 and then find square root of both using Square root under mod P. Then use Chinese Remainder Theorem to find the square root modulo p1 * p2. Each set will contain two equations (as there are two square roots each for modulo p1 and p2). Combining them all, four sets of equations are obtained which gives the four possible answers.
Follow the steps below to solve this problem:

• Factorize the number P by using Prime Factorization. Factors will be two primes p1 and p2.
• Find square root modulo primes p1 and p2.
• Two sets for answers is found, one for each prime. Each set containing two numbers.
• So there will be 4 set of equations if one number from each set is chosen.
• Perform Chinese Remainder Theorem to find the square root modulo p1 * p2 and print them.

Below is the implementation of the above approach where BigInteger class in Java is used to handle very large numbers:

## Java

 `// Java program for the above approach` `import` `java.math.*;` `import` `java.util.*;`   `class` `SqrtMod {`   `    ``// Function to find the modulo inverse` `    ``// of a with respect to m` `    ``static` `BigInteger modInverse(BigInteger a,` `                                 ``BigInteger m)` `    ``{`   `        ``BigInteger m0 = m;` `        ``BigInteger y = ``new` `BigInteger(``"0"``),` `                   ``x = ``new` `BigInteger(``"1"``);`   `        ``if` `(m.compareTo(``new` `BigInteger(``"1"``)) == ``0``)` `            ``return` `new` `BigInteger(``"0"``);`   `        ``// Perform Extended Euclid Algorithm` `        ``while` `(a.compareTo(``new` `BigInteger(``"1"``)) > ``0``) {`   `            ``if` `(m.toString().equals(``"0"``))` `                ``break``;` `            ``BigInteger q = a.divide(m);`   `            ``BigInteger t = m;`   `            ``// M is remainder now, process` `            ``// Extended Euclid Algorithm` `            ``m = a.mod(m);` `            ``a = t;`   `            ``t = y;` `            ``y = x.subtract(q.multiply(y));` `            ``x = t;` `        ``}`   `        ``// Make x positive` `        ``while` `(x.compareTo(``new` `BigInteger(``"0"``)) < ``0``)` `            ``x = x.add(m0);` `        ``return` `x;` `    ``}`   `    ``// Function to apply the Chinese` `    ``// Remainder Theorem` `    ``static` `String CRT(BigInteger num[],` `                      ``BigInteger rem[],` `                      ``int` `k)` `    ``{`   `        ``BigInteger prod = ``new` `BigInteger(``"1"``);`   `        ``// Find product of all numbers` `        ``for` `(``int` `i = ``0``; i < k; i++)` `            ``prod = prod.multiply(num[i]);`   `        ``BigInteger result = ``new` `BigInteger(``"0"``);`   `        ``// Apply the above formula` `        ``for` `(``int` `i = ``0``; i < k; i++) {` `            ``BigInteger pp = prod.divide(num[i]);` `            ``result = result.add(rem[i]` `                                    ``.multiply(modInverse(pp,` `                                                         ``num[i]))` `                                    ``.multiply(pp));` `        ``}`   `        ``// Return result` `        ``return` `result.mod(prod).toString();` `    ``}`   `    ``// Function to perform modular` `    ``// exponentiation` `    ``static` `BigInteger powMod(BigInteger base1,` `                             ``BigInteger exponent,` `                             ``BigInteger modulus)` `    ``{`   `        ``BigInteger result = ``new` `BigInteger(``"1"``);`   `        ``base1 = base1.mod(modulus);`   `        ``while` `(exponent` `                   ``.compareTo(``new` `BigInteger(``"0"``))` `               ``> ``0``) {`   `            ``if` `(exponent` `                    ``.mod(``new` `BigInteger(``"2"``))` `                    ``.equals(``new` `BigInteger(``"1"``)))`   `                ``result = (result.multiply(base1))` `                             ``.mod(modulus);`   `            ``exponent = exponent` `                           ``.divide(``new` `BigInteger(``"2"``));`   `            ``base1 = base1` `                        ``.multiply(base1)` `                        ``.mod(modulus);` `        ``}`   `        ``// Return the result` `        ``return` `result;` `    ``}`   `    ``// Function that returns square root` `    ``// of n under modulo p if exists` `    ``static` `BigInteger squareRoot(` `        ``BigInteger n,` `        ``BigInteger p)` `    ``{`   `        ``// For Invalid Input` `        ``if` `(!p.mod(``new` `BigInteger(``"4"``))` `                 ``.equals(``new` `BigInteger(``"3"``))) {`   `            ``System.out.print(``"Invalid Input"``);` `            ``return` `new` `BigInteger(``"-1"``);` `        ``}`   `        ``n = n.mod(p);`   `        ``// Try "+(n^((p + 1)/4))"` `        ``BigInteger x = powMod(n,` `                              ``(p.add(``new` `BigInteger(``"1"``)))` `                                  ``.divide(``new` `BigInteger(``"4"``)),` `                              ``p);`   `        ``if` `((x.multiply(x)).mod(p).equals(n)) {` `            ``return` `x;` `        ``}`   `        ``// Try "-(n ^ ((p + 1)/4))"` `        ``x = p.subtract(x);` `        ``if` `((x.multiply(x)).mod(p).equals(n)) {` `            ``return` `x;` `        ``}`   `        ``// If none of above two work,` `        ``// then sqrt doesn't exist` `        ``return` `new` `BigInteger(``"-1"``);` `    ``}`   `    ``// Function to find the ceiling` `    ``// of square root of a number` `    ``public` `static` `BigInteger` `    ``sqrtC(BigInteger x)` `    ``{`   `        ``// If number < zero` `        ``if` `(x.compareTo(BigInteger.ZERO) < ``0``) {` `            ``return` `new` `BigInteger(``"-1"``);` `        ``}`   `        ``// If number is zero or 1` `        ``if` `(x == BigInteger.ZERO` `            ``|| x == BigInteger.ONE) {` `            ``return` `x;` `        ``}`   `        ``BigInteger two` `            ``= BigInteger.valueOf(2L);`   `        ``BigInteger y;`   `        ``// Iterate to find the square root` `        ``for` `(y = x.divide(two);` `             ``y.compareTo(x.divide(y)) > ``0``;` `             ``y = ((x.divide(y)).add(y)).divide(two))` `            ``;` `        ``if` `(x.compareTo(y.multiply(y)) == ``0``) {` `            ``return` `y;` `        ``}` `        ``else` `{` `            ``return` `y.add(BigInteger.ONE);` `        ``}` `    ``}`   `    ``// Function to factorise number P` `    ``static` `BigInteger[] factorise(BigInteger p)` `    ``{`   `        ``BigInteger ans[] = ``new` `BigInteger[``2``];` `        ``BigInteger b = ``new` `BigInteger(``"2"``);`   `        ``BigInteger ONE = ``new` `BigInteger(``"1"``);` `        ``BigInteger ZERO = ``new` `BigInteger(``"0"``);`   `        ``// Iterate over [2, sqrt(N)]` `        ``for` `(; b.compareTo(` `                   ``sqrtC(p).add(ONE))` `               ``< ``0``;` `             ``b = b.add(ONE)) {`   `            ``// Check if mod is zero` `            ``if` `(p.mod(b).equals(ZERO)) {` `                ``ans[``0``] = b;` `                ``ans[``1``] = p.divide(b);` `            ``}` `        ``}`   `        ``// Return the ans` `        ``return` `ans;` `    ``}`   `    ``// Function to find the all possible` `    ``// squareRoot of a under modulo m` `    ``public` `static` `void` `    ``solve(BigInteger a, BigInteger m)` `    ``{`   `        ``// Find factorization of m` `        ``BigInteger s[] = factorise(m);` `        ``BigInteger ZERO = ``new` `BigInteger(``"0"``);`   `        ``// If number P is not product` `        ``// of two primes` `        ``if` `(!s[``0``].multiply(s[``1``]).equals(m)) {`   `            ``System.out.println(``"Not a product "` `                               ``+ ``"of two primes"``);` `        ``}`   `        ``// Find the numbers` `        ``else` `{`   `            ``BigInteger s1[] = ``new` `BigInteger[``4``];` `            ``BigInteger a1[] = ``new` `BigInteger[``4``];` `            ``BigInteger a2[] = ``new` `BigInteger[``2``];`   `            ``// Find squareRoot` `            ``a1[``0``] = squareRoot(a.mod(s[``0``]), s[``0``]);` `            ``a1[``1``] = squareRoot(a.mod(s[``1``]), s[``1``]);`   `            ``a1[``2``] = a1[``0``].multiply(``new` `BigInteger(``"-1"``));` `            ``a1[``3``] = a1[``1``].multiply(``new` `BigInteger(``"-1"``));`   `            ``// Compare to Zero` `            ``while` `(a1[``2``].compareTo(ZERO) < ``0``)` `                ``a1[``2``] = a1[``2``].add(s[``0``]);` `            ``while` `(a1[``3``].compareTo(ZERO) < ``0``)` `                ``a1[``3``] = a1[``3``].add(s[``1``]);` `            ``s1[``0``] = s[``0``];` `            ``s1[``1``] = s[``1``];` `            ``s1[``2``] = s[``0``];` `            ``s1[``3``] = s[``1``];`   `            ``// Condition for no solution` `            ``if` `(a1[``0``].equals(``new` `BigInteger(``"-1"``))` `                ``|| a1[``1``].equals(``new` `BigInteger(``"-1"``))) {`   `                ``System.out.println(``"No Solution"``);` `            ``}`   `            ``// Else print all possible answers` `            ``else` `{`   `                ``// Perform Chinese Remainder` `                ``// Theorem and print numbers` `                ``System.out.print(` `                    ``CRT(s, a1, ``2``) + ``" "``);`   `                ``a2[``0``] = a1[``0``];` `                ``a2[``1``] = a1[``3``];`   `                ``System.out.print(` `                    ``CRT(s, a2, ``2``) + ``" "``);`   `                ``a2[``0``] = a1[``2``];` `                ``a2[``1``] = a1[``1``];`   `                ``System.out.print(` `                    ``CRT(s, a2, ``2``) + ``" "``);`   `                ``a2[``0``] = a1[``2``];` `                ``a2[``1``] = a1[``3``];`   `                ``System.out.print(` `                    ``CRT(s, a2, ``2``) + ``" "``);` `            ``}` `        ``}` `    ``}`   `    ``// Driver Code` `    ``public` `static` `void` `        ``main(String[] args) ``throws` `Exception` `    ``{`   `        ``// Given Number N` `        ``BigInteger N = ``new` `BigInteger(``"188"``);`   `        ``// Given product of Prime Number` `        ``BigInteger P = ``new` `BigInteger(``"437"``);`   `        ``// Function Call` `        ``solve(N, P);` `    ``}` `}`

Output:

`25 44 393 412`

Time Complexity: O(âˆšP + logN)
Auxiliary Space: O(1)

My Personal Notes arrow_drop_up
Related Articles