From 1c70c27b1b7595ec456bba1b6ee05af581662f6b Mon Sep 17 00:00:00 2001 From: Mayank9207 Date: Thu, 16 Jan 2025 18:08:38 +0530 Subject: [PATCH 1/7] Create Chinese_remainder_theorem.cpp --- .../Chinese_remainder_theorem.cpp | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem.cpp diff --git a/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem.cpp b/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem.cpp new file mode 100644 index 0000000..8941df8 --- /dev/null +++ b/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem.cpp @@ -0,0 +1,64 @@ +#include +#include +using namespace std; + +// Function to find the smallest x such that: +// x % num[i] = rem[i] for all i in [0, k-1] +int chineseRemainder(vector num, vector rem) { + int prod = 1; + + // Compute the product of all numbers in num (product of all moduli) + for (int n : num) + prod *= n; + + // Lambda function to compute the modular inverse of a under modulo m + auto modInverse = [](int a, int m) { + int m0 = m, t, q; + int x0 = 0, x1 = 1; + + // Apply the Extended Euclidean Algorithm + while (a > 1) { + // q is the quotient + q = a / m; + t = m; + // Update m and a (remainder and divisor) + m = a % m, a = t; + t = x0; + // Update coefficients + x0 = x1 - q * x0; + x1 = t; + } + + // Make x1 positive if it is negative + if (x1 < 0) + x1 += m0; + + return x1; + }; + + int result = 0; + + // Loop through each congruence + for (size_t i = 0; i < num.size(); i++) { + int pp = prod / num[i]; // Partial product excluding num[i] + // Add the contribution of the current remainder to the result + result += rem[i] * modInverse(pp, num[i]) * pp; + } + + // Return the result modulo the product of all moduli + return result % prod; +} + +int main() { + // Example usage + vector num = {3, 4, 5}; // Moduli + vector rem = {2, 3, 1}; // Remainders + + // Solve the system of congruences using the Chinese Remainder Theorem + int result = chineseRemainder(num, rem); + + // Output the result + cout << "The solution is " << result << endl; + + return 0; +} From 64531ff047db6a1e7e5330964d948fc9037b8fd4 Mon Sep 17 00:00:00 2001 From: Mayank9207 Date: Thu, 16 Jan 2025 18:09:19 +0530 Subject: [PATCH 2/7] Create Chinese_remainder_theorem.java --- .../Chinese_remainder_theorem.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem.java diff --git a/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem.java b/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem.java new file mode 100644 index 0000000..8ec1abd --- /dev/null +++ b/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem.java @@ -0,0 +1,73 @@ +import java.util.List; +import java.util.ArrayList; + +public class ChineseRemainder { + + // Function to find the smallest x such that: + // x % num[i] = rem[i] for all i in [0, k-1] + public static int chineseRemainder(List num, List rem) { + int prod = 1; + + // Compute the product of all numbers in num (product of all moduli) + for (int n : num) + prod *= n; + + // Function to compute the modular inverse of a under modulo m + int modInverse(int a, int m) { + int m0 = m, t, q; + int x0 = 0, x1 = 1; + + // Apply the Extended Euclidean Algorithm + while (a > 1) { + // q is the quotient + q = a / m; + t = m; + // Update m and a (remainder and divisor) + m = a % m; + a = t; + t = x0; + // Update coefficients + x0 = x1 - q * x0; + x1 = t; + } + + // Make x1 positive if it is negative + if (x1 < 0) + x1 += m0; + + return x1; + } + + int result = 0; + + // Loop through each congruence + for (int i = 0; i < num.size(); i++) { + int pp = prod / num.get(i); // Partial product excluding num[i] + // Add the contribution of the current remainder to the result + result += rem.get(i) * modInverse(pp, num.get(i)) * pp; + } + + // Return the result modulo the product of all moduli + return result % prod; + } + + public static void main(String[] args) { + // Example usage + List num = new ArrayList<>(); + num.add(3); + num.add(4); + num.add(5); // Moduli + + List rem = new ArrayList<>(); + rem.add(2); + rem.add(3); + rem.add(1); // Remainders + + // Solve the system of congruences using the Chinese Remainder Theorem + int result = chineseRemainder(num, rem); + + // Output the result + System.out.println("The solution is " + result); + } +} + From 39926a47f75e482fb7f8cb239006f2d34a96038a Mon Sep 17 00:00:00 2001 From: Mayank9207 Date: Thu, 16 Jan 2025 18:10:24 +0530 Subject: [PATCH 3/7] Create Chinese_remainder_theorem.py --- .../Chinese_remainder_theorem.py | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem.py diff --git a/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem.py b/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem.py new file mode 100644 index 0000000..1ac79c4 --- /dev/null +++ b/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem.py @@ -0,0 +1,56 @@ +from typing import List + +# Function to find the smallest x such that: +# x % num[i] = rem[i] for all i in [0, k-1] +def chinese_remainder(num: List[int], rem: List[int]) -> int: + prod = 1 + + # Compute the product of all numbers in num (product of all moduli) + for n in num: + prod *= n + + # Function to compute the modular inverse of a under modulo m + def mod_inverse(a: int, m: int) -> int: + m0, t, q = m, 0, 0 + x0, x1 = 0, 1 + + # Apply the Extended Euclidean Algorithm + while a > 1: + # q is the quotient + q = a // m + t = m + # Update m and a (remainder and divisor) + m = a % m + a = t + t = x0 + # Update coefficients + x0 = x1 - q * x0 + x1 = t + + # Make x1 positive if it is negative + if x1 < 0: + x1 += m0 + + return x1 + + result = 0 + + # Loop through each congruence + for i in range(len(num)): + pp = prod // num[i] # Partial product excluding num[i] + # Add the contribution of the current remainder to the result + result += rem[i] * mod_inverse(pp, num[i]) * pp + + # Return the result modulo the product of all moduli + return result % prod + +# Example usage +num = [3, 4, 5] # Moduli +rem = [2, 3, 1] # Remainders + +# Solve the system of congruences using the Chinese Remainder Theorem +result = chinese_remainder(num, rem) + +# Output the result +print("The solution is", result) + From 6be105ab7ceaa26ba9262562925cc23d9b4f30c8 Mon Sep 17 00:00:00 2001 From: Mayank9207 Date: Sun, 19 Jan 2025 02:32:31 +0530 Subject: [PATCH 4/7] Create Chinese_remainder_theorem(README).md --- .../Chinese_remainder_theorem(README).md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem(README).md diff --git a/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem(README).md b/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem(README).md new file mode 100644 index 0000000..4eab103 --- /dev/null +++ b/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem(README).md @@ -0,0 +1,31 @@ +## DESCRIPTION + +# Chinese Remainder Theorem + +The Chinese Remainder Theorem (CRT) was discovered by the Chinese mathematician Sun Zi. + +## Formulation + +Let \( m = m₁ × m₂ × ⋯ × mₖ \), where \( mᵢ \) are pairwise coprime. In addition to \( mᵢ \), we are also given a system of congruences: + +a ≡ a₁ (mod m₁) a ≡ a₂ (mod m₂) ⋮ a ≡ aₖ (mod mₖ) + +where \( aᵢ \) are given constants. The original form of CRT states that the given system of congruences always has **one and exactly one solution modulo \( m \)**. + + + +### Condition for Solving the System of Congruences + +For the system of congruences: +x ≡ a₁ (mod m₁) x ≡ a₂ (mod m₂) + +The solution exists if and only if the following condition holds: + +gcd(m₁, m₂) | (a₂ - a₁) + +Where: +- `gcd(m₁, m₂)` is the greatest common divisor (GCD) of the moduli `m₁` and `m₂`, +- `a₁` and `a₂` are the respective remainders. + +This condition means that the difference between `a₂` and `a₁` must be divisible by the greatest common divisor of `m₁` and `m₂` for the system to have a solution. + From 6663a548b5a15755033c64402113eefa4ad10c0b Mon Sep 17 00:00:00 2001 From: Mayank9207 Date: Sun, 19 Jan 2025 11:30:25 +0530 Subject: [PATCH 5/7] Update Chinese_remainder_theorem(README).md --- .../Chinese_remainder_theorem(README).md | 61 ++++++++++++++++--- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem(README).md b/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem(README).md index 4eab103..1f22a3d 100644 --- a/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem(README).md +++ b/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem(README).md @@ -14,18 +14,61 @@ where \( aᵢ \) are given constants. The original form of CRT states that the g -### Condition for Solving the System of Congruences +# Generalized Chinese Remainder Theorem (CRT) for Non-Coprime Moduli -For the system of congruences: -x ≡ a₁ (mod m₁) x ≡ a₂ (mod m₂) +When the moduli m₁, m₂, ..., mₖ are **not pairwise coprime**, the standard Chinese Remainder Theorem cannot be directly applied. However, such systems can still be solved under certain conditions. -The solution exists if and only if the following condition holds: +--- -gcd(m₁, m₂) | (a₂ - a₁) +## Case 1: Moduli Are Not Coprime but the System is Consistent -Where: -- `gcd(m₁, m₂)` is the greatest common divisor (GCD) of the moduli `m₁` and `m₂`, -- `a₁` and `a₂` are the respective remainders. -This condition means that the difference between `a₂` and `a₁` must be divisible by the greatest common divisor of `m₁` and `m₂` for the system to have a solution. +### General Algorithm for Non-Coprime Moduli + +To solve a system of congruences with non-coprime moduli: + +1. **Define the System**: + x ≡ aᵢ (mod mᵢ), for i = 1, 2, ..., k + +2. **Check Pairwise Consistency**: + - For each pair of congruences: + x ≡ aᵢ (mod mᵢ) + x ≡ aⱼ (mod mⱼ) + + - Compute gcd(mᵢ, mⱼ) = g. + - Verify aᵢ ≡ aⱼ (mod g). If this condition is violated, the system is inconsistent. + +3. **Combine Consistent Congruences**: + - Combine congruences iteratively using the least common multiple (lcm) of moduli: + x ≡ a (mod lcm(mᵢ, mⱼ)) + +4. **Solve the Final Reduced System**: + - After reducing all congruences, solve the resulting single congruence. + +--- + +## Example: Solving a System with Non-Coprime Moduli + +Solve the system: +x ≡ 2 (mod 6) +x ≡ 3 (mod 9) + +### Step 1: Check Consistency +- Compute gcd(6, 9) = 3. +- Verify 2 ≡ 3 (mod 3). This condition is satisfied because both leave a remainder of 2 modulo 3. + +### Step 2: Combine Congruences +- Combine the two congruences into one: + x ≡ 2 (mod lcm(6, 9)) = x ≡ 2 (mod 18) + +### Final Solution: +x ≡ 2 (mod 18) + +--- + +## Notes: +- If the system is inconsistent, no solution exists. +- If all moduli are coprime, the standard Chinese Remainder Theorem applies. + +## USE OF CHINESE REMAINDER THEOREM IN SOLVING PROBLEMS From bd70d06ead9559a9a10e3615f5ff31b5ab5c367f Mon Sep 17 00:00:00 2001 From: Mayank9207 Date: Sun, 19 Jan 2025 21:15:34 +0530 Subject: [PATCH 6/7] Update Chinese_remainder_theorem(README).md --- .../Chinese_remainder_theorem(README).md | 218 +++++++++++++++++- 1 file changed, 212 insertions(+), 6 deletions(-) diff --git a/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem(README).md b/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem(README).md index 1f22a3d..d5d8dfe 100644 --- a/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem(README).md +++ b/Number_Theory_Functions/Chinese_remainder_theorem/Chinese_remainder_theorem(README).md @@ -1,6 +1,5 @@ -## DESCRIPTION -# Chinese Remainder Theorem +# **Chinese Remainder Theorem** The Chinese Remainder Theorem (CRT) was discovered by the Chinese mathematician Sun Zi. @@ -13,18 +12,43 @@ a ≡ a₁ (mod m₁) a ≡ a₂ (mod m₂) ⋮ a ≡ aₖ (mod mₖ) where \( aᵢ \) are given constants. The original form of CRT states that the given system of congruences always has **one and exactly one solution modulo \( m \)**. +## Solution for General Case -# Generalized Chinese Remainder Theorem (CRT) for Non-Coprime Moduli +### Direct Construction +A direct construction similar to Lagrange interpolation is possible. -When the moduli m₁, m₂, ..., mₖ are **not pairwise coprime**, the standard Chinese Remainder Theorem cannot be directly applied. However, such systems can still be solved under certain conditions. +Let: + +`Mᵢ := Π_{j ≠ i} mⱼ` + +(the product of all moduli except `mᵢ`) and: + +`Nᵢ := Mᵢ⁻¹ (mod mᵢ)` + +Then, a solution to the system of congruences is: + +`a ≡ Σ_{i=1}^{k} aᵢMᵢNᵢ (mod m₁m₂...mₖ)` --- -## Case 1: Moduli Are Not Coprime but the System is Consistent +### Verification +We can check this is indeed a solution by computing `a (mod mᵢ)` for all `i`. Because `Mⱼ` is a multiple of `mᵢ` for `i ≠ j`, we have: + +`a ≡ Σ_{j=1}^{k} aⱼMⱼNⱼ (mod mᵢ)` + +`≡ aᵢMᵢNᵢ (mod mᵢ)` +`≡ aᵢMᵢMᵢ⁻¹ (mod mᵢ)` +`≡ aᵢ (mod mᵢ)` -### General Algorithm for Non-Coprime Moduli + + +### Generalized Chinese Remainder Theorem (CRT) for Non-Coprime Moduli + +When the moduli m₁, m₂, ..., mₖ are **not pairwise coprime**, the standard Chinese Remainder Theorem cannot be directly applied. However, such systems can still be solved under certain conditions. + +--- To solve a system of congruences with non-coprime moduli: @@ -72,3 +96,185 @@ x ≡ 2 (mod 18) - If all moduli are coprime, the standard Chinese Remainder Theorem applies. ## USE OF CHINESE REMAINDER THEOREM IN SOLVING PROBLEMS +Problem: Multiple Congruences with Mixed Moduli and Constraints + +Sure! Let's tackle a more complex problem that involves the Chinese Remainder Theorem (CRT). Here's a more challenging problem that would require using CRT, along with some advanced concepts like handling large inputs, dealing with constraints, and considering edge cases. + +Problem: Multiple Congruences with Mixed Moduli and Constraints +You are given several systems of congruences. Each system can have different moduli and constraints. Your goal is to use the Chinese Remainder Theorem to solve this. + +### Problem Statement: + +Given a system of `n` congruences of the form: +x ≡ a₁ (mod m₁) x ≡ a₂ (mod m₂) ... x ≡ aₙ (mod mₙ) + +Where `mᵢ` and `mⱼ` (for all `i ≠ j`) are **not necessarily coprime** (i.e., they may share common factors). The task is to find the smallest `x` that satisfies all these congruences, or determine that there is **no solution**. + +### Input Format: +- The first line contains a single integer `n` — the number of congruences. +- The second line contains `n` space-separated integers, each representing a modulus: `m₁, m₂, ..., mₙ`. +- The third line contains `n` space-separated integers, each representing the corresponding remainder: `a₁, a₂, ..., aₙ`. + + + +### Output Format: +- If a solution exists, output the smallest `x` that satisfies all the congruences. +- If no solution exists, output `No solution`. + +Here,to solve this problem, we have to use the extended form of chinese remainder theorem as the given moduli are not given to be coprime i.e. +gcd(mi,mj)|abs(ai-aj) + + +The following code shows the implementation of above logic + + +```cpp +#include +#include +#include // For gcd +using namespace std; + +// Function to find the modular inverse of a under modulo m (when gcd(a, m) == 1) +int modInverse(int a, int m) { + int m0 = m, t, q; + int x0 = 0, x1 = 1; + + while (a > 1) { + q = a / m; + t = m; + m = a % m; + a = t; + t = x0; + x0 = x1 - q * x0; + x1 = t; + } + + if (x1 < 0) + x1 += m0; + + return x1; +} + +// Function to solve the system of congruences using the Chinese Remainder Theorem +int chineseRemainder(vector num, vector rem) { + int prod = 1; + + // Compute the product of all numbers in num (product of all moduli) + for (int n : num) + prod *= n; + + int result = 0; + + // Loop through each congruence + for (size_t i = 0; i < num.size(); i++) { + int pp = prod / num[i]; // Partial product excluding num[i] + result += rem[i] * modInverse(pp, num[i]) * pp; + } + + // Return the result modulo the product of all moduli + return result % prod; +} + +// Function to check if the system of congruences is solvable +bool isSolvable(const vector& num, const vector& rem) { + int n = num.size(); + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + int g = gcd(num[i], num[j]); + if (g > 1 && abs(rem[i] - rem[j]) % g != 0) { + return false; // If gcd doesn't divide the difference of remainders, no solution + } + } + } + return true; +} + +// Function to solve the system of congruences even when moduli are not coprime +bool extendedChineseRemainder(vector& num, vector& rem) { + int n = num.size(); + + // Loop through the moduli and solve pairwise + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + int g = gcd(num[i], num[j]); + // Check if the difference of remainders is divisible by the gcd + if (abs(rem[i] - rem[j]) % g != 0) { + return false; // No solution if this condition fails + } + + // Solve pairwise congruences using the Extended Euclidean Algorithm + int x1 = rem[i], x2 = rem[j]; + int m1 = num[i], m2 = num[j]; + + // Calculate the combined modulus + int newMod = (m1 * m2) / g; + int newRem = 0; + + // Solve the pairwise system (x1 mod m1) and (x2 mod m2) + int g1, x, y; + extendedGCD(m1, m2, g1, x, y); + x = ((x * (x2 - x1) / g) % (m2)) + m1; + newRem = (x * m1 + x1) % newMod; + + // Update moduli and remainders for the new system + num[i] = newMod; + rem[i] = newRem; + } + } + + return true; +} + +// Function to find the Extended GCD of two numbers (also computes the coefficients x and y such that ax + by = gcd(a, b)) +void extendedGCD(int a, int b, int& g, int& x, int& y) { + if (a == 0) { + g = b; + x = 0; + y = 1; + return; + } + + int x1, y1; + extendedGCD(b % a, a, g, x1, y1); + x = y1 - (b / a) * x1; + y = x1; +} + +// Driver code +int main() { + int n; + cin >> n; + + vector num(n); + vector rem(n); + + // Input the moduli and remainders + for (int i = 0; i < n; i++) { + cin >> num[i]; + } + + for (int i = 0; i < n; i++) { + cin >> rem[i]; + } + + // Check if the system is solvable + if (!isSolvable(num, rem)) { + cout << "No solution" << endl; + return 0; + } + + // Solve the system of congruences using the Extended Chinese Remainder Theorem + if (!extendedChineseRemainder(num, rem)) { + cout << "No solution" << endl; + } else { + int result = chineseRemainder(num, rem); + cout << result << endl; + } + + return 0; +} + + + + +``` From f758b473239cb3bd65b7d55cddfe70ebf089db41 Mon Sep 17 00:00:00 2001 From: Mayank9207 Date: Mon, 20 Jan 2025 04:10:56 +0530 Subject: [PATCH 7/7] Update RoadMap.md --- RoadMap.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RoadMap.md b/RoadMap.md index edbd2bc..d59cbd2 100644 --- a/RoadMap.md +++ b/RoadMap.md @@ -38,6 +38,7 @@ These are fundamental algorithms and functions often used in competitive program - [x] [Get Factorial upto 'n' (with modulus)](Number_Theory_Functions/Factorial_array) - [x] [Get Inverse Factorial upto 'n' (with modulus) (return an array)](Number_Theory_Functions/computeInverseFactorials) - [x] nPr (Permutation with modulus) +- [x] [Chinese_Remainder_theorem](Number_Theory_Functions/Chinese_remainder_theorem) - [ ] nCr (Combination with modulus)