📜  中国剩余定理|设置1(简介)

📅  最后修改于: 2021-04-29 07:26:44             🧑  作者: Mango

我们给了两个数组num [0..k-1]和rem [0..k-1]。在num [0..k-1]中,每对都是互质的(每对gcd为1)。我们需要找到最小正数x,使得:

x % num[0]    =  rem[0], 
     x % num[1]    =  rem[1], 
     .......................
     x % num[k-1]  =  rem[k-1] 

基本上,给我们k个数,它们是成对的互质数,当未知数x除以它们时,给出这些数的余数。我们需要找到产生给定余数的x的最小可能值。
例子 :

Input:  num[] = {5, 7}, rem[] = {1, 3}
Output: 31
Explanation: 
31 is the smallest number such that:
  (1) When we divide it by 5, we get remainder 1. 
  (2) When we divide it by 7, we get remainder 3.

Input:  num[] = {3, 4, 5}, rem[] = {2, 3, 1}
Output: 11
Explanation: 
11 is the smallest number such that:
  (1) When we divide it by 3, we get remainder 2. 
  (2) When we divide it by 4, we get remainder 3.
  (3) When we divide it by 5, we get remainder 1.

中国剩余定理指出,始终存在满足给定全等的x。以下是从维基百科改编的定理陈述。
令num [0],num [1],…num [k-1]是成对的互质数的正整数。然后,对于任何给定的整数rem [0],rem [1],…rem [k-1]序列,都存在一个整数x,它求解以下同时同余的系统。

中国剩余

第一部分很清楚,存在一个x。第二部分基本上指出,当n [0],num [1],.. num [k-1]的副产品相除时,所有解(包括最小解)都会产生相同的余数。在上面的示例中,乘积为3 * 4 * 5 =60。11是一个解决方案,其他解决方案是71、131等。所有这些解决方案在除以60时都会产生相同的余数,即它们是形式11 + m * 60,其中m> = 0。
一种简单的查找x的方法是从1开始,然后以一个递增的方式递增x ,然后检查是否将其与num []中的给定元素相除会在rem []中产生相应的余数。一旦找到这样的x,我们将其返回。
以下是朴素方法的实现。

C++
// A C++ program to demonstrate working of Chinise remainder
// Theorem
#include
using namespace std;
 
// k is size of num[] and rem[].  Returns the smallest
// number x such that:
//  x % num[0] = rem[0],
//  x % num[1] = rem[1],
//  ..................
//  x % num[k-2] = rem[k-1]
// Assumption: Numbers in num[] are pairwise coprime
// (gcd for every pair is 1)
int findMinX(int num[], int rem[], int k)
{
    int x = 1; // Initialize result
 
    // As per the Chinese remainder theorem,
    // this loop will always break.
    while (true)
    {
        // Check if remainder of x % num[j] is
        // rem[j] or not (for all j from 0 to k-1)
        int j;
        for (j=0; j


Java
// A Java program to demonstrate the working of Chinese remainder
// Theorem
import java.io.*;
 
class GFG {
     
    // k is size of num[] and rem[].  Returns the smallest
    // number x such that:
    //  x % num[0] = rem[0],
    //  x % num[1] = rem[1],
    //  ..................
    //  x % num[k-2] = rem[k-1]
    // Assumption: Numbers in num[] are pairwise coprime
    // (gcd for every pair is 1)
    static int findMinX(int num[], int rem[], int k)
    {
        int x = 1; // Initialize result
      
        // As per the Chinese remainder theorem,
        // this loop will always break.
        while (true)
        {
            // Check if remainder of x % num[j] is
            // rem[j] or not (for all j from 0 to k-1)
            int j;
            for (j=0; j


Python3
# A Python3 program to demonstrate
# working of Chinise remainder Theorem
 
# k is size of num[] and rem[].
# Returns the smallest number x
# such that:
# x % num[0] = rem[0],
# x % num[1] = rem[1],
# ..................
# x % num[k-2] = rem[k-1]
# Assumption: Numbers in num[]
# are pairwise coprime (gcd for
# every pair is 1)
def findMinX(num, rem, k):
    x = 1; # Initialize result
 
    # As per the Chinise remainder
    # theorem, this loop will
    # always break.
    while(True):
         
        # Check if remainder of
        # x % num[j] is rem[j]
        # or not (for all j from
        # 0 to k-1)
        j = 0;
        while(j < k):
            if (x % num[j] != rem[j]):
                break;
            j += 1;
 
        # If all remainders
        # matched, we found x
        if (j == k):
            return x;
 
        # Else try next numner
        x += 1;
 
# Driver Code
num = [3, 4, 5];
rem = [2, 3, 1];
k = len(num);
print("x is", findMinX(num, rem, k));
 
# This code is contributed by mits


C#
// C# program to demonstrate working
// of Chinise remainder Theorem
using System;
 
class GFG
{
     
    // k is size of num[] and rem[].
    // Returns the smallest
    // number x such that:
    // x % num[0] = rem[0],
    // x % num[1] = rem[1],
    // ..................
    // x % num[k-2] = rem[k-1]
    // Assumption: Numbers in num[]
    // are pairwise coprime
    // (gcd for every pair is 1)
    static int findMinX(int []num, int []rem,
                        int k)
    {
         
        // Initialize result
        int x = 1;
     
        // As per the Chinese remainder theorem,
        // this loop will always break.
        while (true)
        {
            // Check if remainder of x % num[j] is
            // rem[j] or not (for all j from 0 to k-1)
            int j;
            for (j = 0; j < k; j++ )
                if (x % num[j] != rem[j])
                break;
     
            // If all remainders matched, we found x
            if (j == k)
                return x;
     
            // Else try next numner
            x++;
        }
     
    }
     
    // Driver code
    public static void Main()
    {
        int []num = {3, 4, 5};
        int []rem = {2, 3, 1};
        int k = num.Length;
        Console.WriteLine("x is " + findMinX(num,
                                        rem, k));
    }
}
 
// This code is contributed by Sam007.


PHP


Javascript


输出 :

x is 11

时间复杂度: O(M),M是num []数组的所有元素的乘积。

辅助空间: O(1)