Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 10

Solving Linear Congruences

Recommended resources

Hello again! In our previous lesson, you learned how to perform modular division, , by transforming it into a multiplication with the modular inverse. This was a crucial step, but it came with a key assumption: the modulus had to be prime. Today, we generalize this concept to solve equations of the form , known as linear congruences.

This lesson tackles the problem for any modulus , prime or composite, and situations where the relationship between and is more complex. You'll learn when solutions exist, how many there are, and a systematic method to find them. This skill is essential for a wide range of competitive programming problems that go beyond the ideal conditions of prime moduli.

From Modular Division to Linear Congruences

In the last lesson, when you calculated , you were implicitly finding a number such that . If you multiply both sides by , you get . So, modular division is just one specific case of solving a linear congruence where an inverse of is guaranteed to exist.

But what happens if is not prime, or if and share common factors? In these cases, the modular inverse might not exist. Does that mean there's no solution? Not necessarily. The equation provides a more powerful framework that can still have solutions.

Let's explore the general case. We are looking for all integer values of in the range that satisfy the equation.


Conditions for a Solution

The first step is to determine if a solution even exists. An elegant rule governs this, based on the greatest common divisor (GCD) of and .

A linear congruence has a solution if and only if divides .

Why is this true? The expression means for some integer . Let . Since divides both and , it must also divide any linear combination of them, including . Therefore, for the equation to hold, must also divide . If is not divisible by , no integer can satisfy the congruence.

Furthermore, if solutions do exist, there are exactly distinct solutions modulo .

The following resource from cp-algorithms.com, a staple for competitive programmers, explains this condition clearly.

Linear Congruence Equation

This article provides a concise and clear explanation of solving linear congruences. It's perfectly suited for our competitive programming context.

Read the section titled "Solution by finding the inverse element." Pay close attention to the second half, starting from the case where a and n are not coprime. The key takeaways are the condition for no solution and the statement that the equation has exactly g solutions.


A Step-by-Step Method to Find All Solutions

Now that we know the conditions, let's establish a method to find the solutions. The strategy is to simplify the original congruence into one where an inverse does exist, find a single solution, and then use it to generate all other solutions.

Let .

  1. Check for Solvability: If is not divisible by , stop. There are no solutions.
  2. Reduce the Congruence: If a solution exists, we can divide the entire congruence (all three parts: , , and ) by . This gives us a new, equivalent congruence:

    Let's call this . A crucial property is that now .
  3. Find One Particular Solution (): Since , we know that has a modular multiplicative inverse modulo . We can solve for by multiplying both sides by this inverse:

    This gives us our first solution, which we'll call .
    • How to find ? If is prime, you can use Fermat's Little Theorem as you learned before. If is composite (and are coprime), you need a more general method. The standard algorithm for this is the Extended Euclidean Algorithm, which we will cover in detail in our very next lesson! For now, if is small, you can find the inverse by inspection (i.e., testing small numbers).
  4. Generate All Solutions: The original congruence has solutions. We have found one, , which is correct modulo . All solutions modulo are given by:

    This generates distinct solutions in the range .

A Worked Example

Let's solidify this with an example. Watch this video from Michael Penn, which walks through solving 140x ≡ 56 (mod 252).

Number Theory | Linear Congruence Example 2

This video provides a clear, step-by-step walkthrough of solving a non-trivial linear congruence, perfectly illustrating the method we just outlined.

Watch the entire video. It's short and to the point. The initial analysis where he determines that solutions exist and how many there are using the GCD. The reduction step, where the original congruence is simplified by dividing by the GCD. Solving the reduced congruence by finding an inverse by inspection and getting the first solution, x = 4. Generating all solutions based on the first solution and the number of expected solutions.

Let's retrace the video's steps using our method:

  • Equation:
  • Step 1: Check Solvability
    • You can use the Euclidean algorithm (from Module 1) to find .
    • Does 28 divide 56? Yes, .
    • Conclusion: There are exactly 28 solutions.
  • Step 2: Reduce the Congruence
    • Divide by .
    • The new congruence is .
  • Step 3: Find One Solution
    • We need to find . Since 9 is small and composite, we can't use Fermat's Little Theorem. We test values: , . The inverse is 2.
    • .
    • Our first solution is .
  • Step 4: Generate All Solutions
    • The solutions are of the form , for .
    • The solutions are: 4, 13, 22, 31, ..., 247.

Looking Ahead: The Master Key

Our method relies on finding the modular inverse . As mentioned, this is simple for prime but requires a more powerful tool for composite . This tool is the Extended Euclidean Algorithm, which finds integer solutions to equations of the form .

The linear congruence can be rewritten as for some integer . This is a Linear Diophantine Equation, and the Extended Euclidean Algorithm is the fundamental method for solving it.

This video gives an excellent intuitive derivation, showing how the problem of finding an inverse or solving a congruence transforms into the ax + by = c form that the Extended Euclidean Algorithm solves.

Modulo Inverses, Linear Congruence and Chinese remainder theorem by first principles | Number Theory

This video connects the dots between congruences and the underlying Diophantine equations from first principles.

Watch the segment from linear congruence. The key idea is seeing how ax \equiv b \pmod m is transformed into the equation ax + ym = b, which is exactly the form solved by the algorithm you'll learn next.

While you'll learn the full algorithm in the next lesson, you can already solve many problems. In competitive programming, a simple brute-force approach is often sufficient if the modulus is small.




#include <iostream>
#include <vector>
#include <numeric> // For std::gcd in C++17

// In C++14 or earlier, you'd have to implement gcd yourself.
/*
long long gcd(long long a, long long b) {
    while (b) {
        a %= b;
        std::swap(a, b);
    }
    return a;
}
*/

void solve_linear_congruence(long long a, long long b, long long m) {
    a %= m;
    b %= m;
    
    // For competitive programming with small m, this is a valid strategy.
    std::vector<long long> solutions;
    for (long long x = 0; x < m; ++x) {
        if ((a * x) % m == b) {
            solutions.push_back(x);
        }
    }

    if (solutions.empty()) {
        std::cout << "No solutions." << std::endl;
    } else {
        std::cout << "Solutions: ";
        for (long long sol : solutions) {
            std::cout << sol << " ";
        }
        std::cout << std::endl;
    }
}

int main() {
    // Example from the lesson: 140x ≡ 56 (mod 252)
    // The solutions are 4, 13, 22, ...
    solve_linear_congruence(140, 56, 252); 

    // Example with no solution: 2x ≡ 1 (mod 4)
    // gcd(2, 4) = 2, which does not divide 1.
    solve_linear_congruence(2, 1, 4);
    return 0;
}

This brute-force code simply checks every possible value of . It's too slow for large , but for up to or so, it can pass within time limits. The analytical method is always better and necessary for large moduli.


Conclusion

In this lesson, you've moved beyond the simple case of modular division and tackled the general problem of solving linear congruences.

Here are the key takeaways:

  • A linear congruence has solutions if and only if divides .
  • If solutions exist, there are exactly distinct solutions modulo .
  • The general strategy is to reduce the congruence by dividing all parts by , solve the simpler congruence, and then generate all solutions from the one you found.
  • Solving the reduced congruence requires finding a modular inverse, which you can do with Fermat's Little Theorem (if the new modulus is prime) or by inspection (if small).

You now have a complete conceptual map for solving these equations. The final missing piece is the efficient implementation for the hardest case: finding a modular inverse with a large, composite modulus. Our next lesson will give you that key by introducing the Extended Euclidean Algorithm, a cornerstone of number theory in competitive programming.