Skip to content
Related Articles

Related Articles

Save Article
Improve Article
Save Article
Like Article

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

  • Difficulty Level : Medium
  • Last Updated : 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:

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Input: A=15, B=9, N=18
Output: 15, 3, 9
Explanation: 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=30
Output: 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:

  1. Given, AX=B (mod N)
    ⇒ there exist a number Y such that AX=B+NY
    AX-NY=B — (1)
    This is a linear Diophantine equation, and is solvable if and only if GCD(A, N) divides B.
  2. 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)
  3. 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.
  4. 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++




// 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 Code
int main()
{
    // Input
    long long A = 15;
    long long B = 9;
    long long N = 18;
 
    // Function Call
    linearCongruence(A, B, N);
 
    return 0;
}

Java




// Java program for the above approach
import 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 Code
public 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




# 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
 
# Input
A = 15
B = 9
N = 18
 
# Function Call
linearCongruence(A, B, N)
 
# This code is contributed by SHUBHAMSINGH10

C#




// C# program for the above approach
using 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

Javascript




<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>
Output
15 3 9 

Time Complexity: O(log(min(A, N))
Auxiliary Space: O(1)

 




My Personal Notes arrow_drop_up
Recommended Articles
Page :