Solve Linear Congruences Ax = B (mod N) for values of x in range [0, N-1]

12 Jul, 2021
Given three positive integers A, B, and N, which represent a linear congruence of the form AX=B (mod N), the task is to print all possible values of X (mod N) i.e in the range [0, N-1] that satisfies this equation. If there is no solution, print -1.
Examples:
Input: A=15, B=9, N=18Output: 15, 3, 9Explanation: The values of X satisfying the condition AX=B (mod N) are {3, 9, 15}.(15*15)%18 = 225%18=9(3*15)%18 = 45%18=9(9*15)%18 = 135%18=9
Input: A=9, B=21, N=30Output: 9, 19, 20
Approach: The idea is based on the following observations:
A solution exists if and only if B is divisible by GCD(A, N) i.e B%GCD(A, N)=0.
The number of solutions for X (mod N) is GCD(A, N).
Proof:
Given, AX=B (mod N)⇒ there exist a number Y such that AX=B+NYAX-NY=B — (1)This is a linear Diophantine equation, and is solvable if and only if GCD(A, N) divides B.Now, using the Extended Euclidean Algorithm, u and v can be found such that Au+Nv=GCD(A, N)=d(say)⇒ Au+Nv=d⇒ Au=d (mod N) — (2)Assuming B%d=0, so that solution of Equation 1 exists, Multiplying both sides of Equation 2 by B/d, (possible since B/d is an integer), Au*(B/d)=d*(B/d) (mod N) or A*(u*B/d)=B (mod N).Thus, u*B/d is a solution of Equation 1.Let X0 be u*B/d.Thus, the d solutions of Equation 1 will be X0, X0+(N/d), X0+2*(N/d), ..., X0+(d-1)*(N/d)
Given, AX=B (mod N)⇒ there exist a number Y such that AX=B+NYAX-NY=B — (1)This is a linear Diophantine equation, and is solvable if and only if GCD(A, N) divides B.
Now, using the Extended Euclidean Algorithm, u and v can be found such that Au+Nv=GCD(A, N)=d(say)⇒ Au+Nv=d⇒ Au=d (mod N) — (2)
Assuming B%d=0, so that solution of Equation 1 exists, Multiplying both sides of Equation 2 by B/d, (possible since B/d is an integer), Au*(B/d)=d*(B/d) (mod N) or A*(u*B/d)=B (mod N).Thus, u*B/d is a solution of Equation 1.
Let X0 be u*B/d.Thus, the d solutions of Equation 1 will be X0, X0+(N/d), X0+2*(N/d), ..., X0+(d-1)*(N/d)
Follow the steps below to solve the problem:
Initialize variable d as GCD(A, N) as well as u using the Extended Euclidean Algorithm.
If B is not divisible by d, print -1 as the result.
Else iterate in the range [0, d-1] using the variable i and in each iteration print the value of u*(B/d)+i*(N/d).
Below is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
// C++ program for the above approach#include <bits/stdc++.h>using namespace std; // Function to stores the values of x and y// and find the value of gcd(a, b)long long ExtendedEuclidAlgo(    long long a, long long b,    long long& x, long long& y){    // Base Case    if (b == 0) {        x = 1;        y = 0;        return a;    }    else {         // Store the result of recursive call        long long x1, y1;        long long gcd            = ExtendedEuclidAlgo(b, a % b, x1, y1);         // Update x and y using results of        // recursive call        x = y1;        y = x1 - floor(a / b) * y1;         return gcd;    }} // Function to give the distinct// solutions of ax = b (mod n)void linearCongruence(long long A,                      long long B,                      long long N){    A = A % N;    B = B % N;     long long u = 0, v = 0;     // Function Call to find    // the value of d and u    long long d = ExtendedEuclidAlgo(A, N, u, v);     // No solution exists    if (B % d != 0) {        cout << -1 << endl;        return;    }     // Else, initialize the value of x0    long long x0 = (u * (B / d)) % N;    if (x0 < 0)        x0 += N;     // Print all the answers    for (long long i = 0; i <= d - 1; i++)        cout << (x0 + i * (N / d)) % N << " ";} // Driver Codeint main(){    // Input    long long A = 15;    long long B = 9;    long long N = 18;     // Function Call    linearCongruence(A, B, N);     return 0;}
// Java program for the above approachimport java.io.*; class GFG{     // Function to stores the values of x and y// and find the value of gcd(a, b)public static long[] ExtendedEuclidAlgo(long a,                                        long b){         // Base Case    if (a == 0)    {        return new long[]{b, 0, 1};    }    else    {                 // Store the result of recursive call        long x1 = 1, y1 = 1;        long gcdy[] = ExtendedEuclidAlgo(b % a, a);        long gcd = gcdy[0];        x1 = gcdy[1];        y1 = gcdy[2];         // Update x and y using results of        // recursive call        long y = x1;        long x = y1 - (long)Math.floor(b / a) * x1;         return new long[] {gcd, x, y};    }} // Function to give the distinct// solutions of ax = b (mod n)public static void linearCongruence(long A,                                    long B,                                    long N){    A = A % N;    B = B % N;         long u = 0, v = 0;     // Function Call to find    // the value of d and u    long person[] = ExtendedEuclidAlgo(A, N);    long d = person[0];    u = person[1];    v = person[2];     // No solution exists    if (B % d != 0)    {        System.out.println(-1);        return;    }     // Else, initialize the value of x0    long x0 = (u * (B / d)) % N;    if (x0 < 0)        x0 += N;         // Print all the answers    for(long i = 0; i <= d - 1; i++)    {        long an = (x0 + i * (N / d)) % N;        System.out.print(an + " ");    }} // Driver Codepublic static void main(String[] args){         // Input    long A = 15;    long B = 9;    long N = 18;     // Function Call    linearCongruence(A, B, N);}} // This code is contributed by Shubhamsingh10
# Python3 program for the above approach # Function to stores the values of x and y# and find the value of gcd(a, b)def ExtendedEuclidAlgo(a, b):         # Base Case    if a == 0 :        return b, 0, 1             gcd, x1, y1 = ExtendedEuclidAlgo(b % a, a)         # Update x and y using results of recursive    # call    x = y1 - (b // a) * x1    y = x1         return gcd, x, y     # Function to give the distinct# solutions of ax = b (mod n)def linearCongruence(A, B, N):         A = A % N    B = B % N    u = 0    v = 0         # Function Call to find    # the value of d and u    d, u, v = ExtendedEuclidAlgo(A, N)         # No solution exists    if (B % d != 0):        print(-1)        return         # Else, initialize the value of x0    x0 = (u * (B // d)) % N    if (x0 < 0):        x0 += N         # Pr all the answers    for i in range(d):        print((x0 + i * (N // d)) % N, end = " ") # Driver Code # InputA = 15B = 9N = 18 # Function CalllinearCongruence(A, B, N) # This code is contributed by SHUBHAMSINGH10
// C# program for the above approachusing System; class GFG{         // Function to stores the values of x and y    // and find the value of gcd(a, b)    public static long[] ExtendedEuclidAlgo(long a,                                            long b)    {                 // Base Case        if (a == 0)        {            return new long[]{b, 0, 1};        }        else        {                         // Store the result of recursive call            long x1 = 1, y1 = 1;            long[] gcdy = ExtendedEuclidAlgo(b % a, a);            long gcd = gcdy[0];            x1 = gcdy[1];            y1 = gcdy[2];                 // Update x and y using results of            // recursive call            long y = x1;            long x = y1 - (long)(b / a) * x1;                 return new long[] {gcd, x, y};        }    }         // Function to give the distinct    // solutions of ax = b (mod n)    public static void linearCongruence(long A,                                        long B,                                        long N)    {        A = A % N;        B = B % N;                 long u = 0, v = 0;             // Function Call to find        // the value of d and u        long []person = ExtendedEuclidAlgo(A, N);        long d = person[0];        u = person[1];        v = person[2];             // No solution exists        if (B % d != 0)        {            Console.WriteLine(-1);            return;        }             // Else, initialize the value of x0        long x0 = (u * (B / d)) % N;        if (x0 < 0)            x0 += N;                 // Print all the answers        for(long i = 0; i <= d - 1; i++)        {            long an = (x0 + i * (N / d)) % N;            Console.Write(an + " ");        }    } // Driver Code    static public void Main (){                 // Input        long A = 15;        long B = 9;        long N = 18;             // Function Call        linearCongruence(A, B, N);    }} // This code is contributed by Shubhamsingh10
<script>   // JavaScript program for the above approach // Function to stores the values of x and y// and find the value of gcd(a, b)function ExtendedEuclidAlgo(a, b){         // Base Case    if (a == 0)    {        return [b, 0, 1];    }    else    {                 // Store the result of recursive call        let x1 = 1, y1 = 1;        let gcdy = ExtendedEuclidAlgo(b % a, a);        let gcd = gcdy[0];        x1 = gcdy[1];        y1 = gcdy[2];         // Update x and y using results of        // recursive call        let y = x1;        let x = y1 - Math.floor(b / a) * x1;         return [gcd, x, y];    }} // Function to give the distinct// solutions of ax = b (mod n)function linearCongruence(A, B, N){    A = A % N;    B = B % N;         let u = 0, v = 0;     // Function Call to find    // the value of d and u    let person = ExtendedEuclidAlgo(A, N);    let d = person[0];    u = person[1];    v = person[2];     // No solution exists    if (B % d != 0)    {        document.write(-1);        return;    }     // Else, initialize the value of x0    let x0 = (u * (B / d)) % N;    if (x0 < 0)        x0 += N;         // Print all the answers    for(let i = 0; i <= d - 1; i++)    {        let an = (x0 + i * (N / d)) % N;        document.write(an + " ");    }} // Driver Code     // Input    let A = 15;    let B = 9;    let N = 18;     // Function Call    linearCongruence(A, B, N);         // This code is contributed by sanjoy_62.</script>
15 3 9 
Time Complexity: O(log(min(A, N))Auxiliary Space: O(1)
 
SHUBHAMSINGH10
sanjoy_62
Modular Arithmetic
number-theory
Mathematical
number-theory
Mathematical
Modular Arithmetic
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Algorithm to solve Rubik's Cube
Merge two sorted arrays with O(1) extra space
Program to print prime numbers from 1 to N.
Segment Tree | Set 1 (Sum of given range)
Check if a number is Palindrome
Count ways to reach the n'th stair
Fizz Buzz Implementation
Median of two sorted arrays of same size
Product of Array except itself
Find Union and Intersection of two unsorted arrays