• 数据结构和算法 数论 中国余数定理


    1、中国余数定理概述

            找出所有整数x,它们被3、5、7除时,余数分别为2,3和2。一个这样的解为x = 23,所有的解是形如23 + 105k(k为任意整数)的整数。“中国余数定理”提出,对一组两两互质的模数(如3、5、7)来说,其取模运算的方程组与对其积(如105)取模运算的方程之间存在着一种对应关系。

            中国余数定理被广泛用于计算大整数,因为它允许用几个类似的小整数计算来替换一个知道结果大小界限的计算。

            定理定义如下:给定成对互质正整数n_1, n_2, \cdot \cdot \cdot \cdot \cdot \cdot n_k,和任意整数a_1, a_2, \cdot \cdot \cdot \cdot \cdot \cdot a_k,同时同余系统

            

            有解,且解是唯一的模N = n_1, n_2 \cdots n_k

    2、应用示例

    1. 输入:num[] = {5, 7}, rem[] = {1, 3}
    2. 输出:31
    3. 解释:
    4. 31 是最小的数,使得:
    5. (1) 当我们将它除以 5 时,我们得到余数 1
    6. (2) 当我们将它除以 7 时,我们得到余数 3
    7. 输入:num[] = {3, 4, 5}, rem[] = {2, 3, 1}
    8. 输出:11
    9. 解释:
    10. 11 是最小的数,使得:
    11. (1) 当我们将它除以 3 时,我们得到余数 2
    12. (2) 当我们将它除以 4 时,我们得到余数 3
    13. (3) 当我们将它除以 5 时,我们得到余数 1

    3、应用场景描述

    (1)场景1

            2P/Encke彗星、4P/Faye彗星和8P/Tuttle彗星的轨道周期分别为 3 年、8 年和 13 年。这些彗星的最后一次近日点分别发生在 2017 年、2014 年和 2008 年。

            这三颗彗星都将在同一年达到近日点的明年是什么时候?

            对于这个问题,假设时间以整数年为单位,并且每个轨道周期都是常数。

    (2)场景2

            一所学校的学生人数在 500 到 600 人之间。如果我们将他们分成 12 人、20 人或 36 人一组,则总是剩下 7 名学生。这所学校有多少学生?

    4、代码实现

    (1)c++

    1. #include<bits/stdc++.h>
    2. using namespace std;
    3. // k is size of num[] and rem[]. Returns the smallest
    4. // number x such that:
    5. // x % num[0] = rem[0],
    6. // x % num[1] = rem[1],
    7. // ..................
    8. // x % num[k-2] = rem[k-1]
    9. // Assumption: Numbers in num[] are pairwise coprime
    10. // (gcd for every pair is 1)
    11. int findMinX(int num[], int rem[], int k)
    12. {
    13. int x = 1; // Initialize result
    14. // As per the Chinese remainder theorem,
    15. // this loop will always break.
    16. while (true)
    17. {
    18. // Check if remainder of x % num[j] is
    19. // rem[j] or not (for all j from 0 to k-1)
    20. int j;
    21. for (j=0; j<k; j++ )
    22. if (x%num[j] != rem[j])
    23. break;
    24. // If all remainders matched, we found x
    25. if (j == k)
    26. return x;
    27. // Else try next number
    28. x++;
    29. }
    30. return x;
    31. }
    32. int main(void)
    33. {
    34. int num[] = {3, 4, 5};
    35. int rem[] = {2, 3, 1};
    36. int k = sizeof(num)/sizeof(num[0]);
    37. cout << "x is " << findMinX(num, rem, k);
    38. return 0;
    39. }

    (2)Java

    1. import java.io.*;
    2. class ZGYSDL {
    3. // k is size of num[] and rem[]. Returns the smallest
    4. // number x such that:
    5. // x % num[0] = rem[0],
    6. // x % num[1] = rem[1],
    7. // ..................
    8. // x % num[k-2] = rem[k-1]
    9. // Assumption: Numbers in num[] are pairwise coprime
    10. // (gcd for every pair is 1)
    11. static int findMinX(int num[], int rem[], int k)
    12. {
    13. int x = 1; // Initialize result
    14. // As per the Chinese remainder theorem,
    15. // this loop will always break.
    16. while (true)
    17. {
    18. // Check if remainder of x % num[j] is
    19. // rem[j] or not (for all j from 0 to k-1)
    20. int j;
    21. for (j=0; j<k; j++ )
    22. if (x%num[j] != rem[j])
    23. break;
    24. // If all remainders matched, we found x
    25. if (j == k)
    26. return x;
    27. // Else try next number
    28. x++;
    29. }
    30. }
    31. public static void main(String args[])
    32. {
    33. int num[] = {3, 4, 5};
    34. int rem[] = {2, 3, 1};
    35. int k = num.length;
    36. System.out.println("x is " + findMinX(num, rem, k));
    37. }
    38. }

    (3)Python

    1. # k is size of num[] and rem[].
    2. # Returns the smallest number x
    3. # such that:
    4. # x % num[0] = rem[0],
    5. # x % num[1] = rem[1],
    6. # ..................
    7. # x % num[k-2] = rem[k-1]
    8. # Assumption: Numbers in num[]
    9. # are pairwise coprime (gcd for
    10. # every pair is 1)
    11. def findMinX(num, rem, k):
    12. x = 1; # Initialize result
    13. # As per the Chinise remainder
    14. # theorem, this loop will
    15. # always break.
    16. while(True):
    17. # Check if remainder of
    18. # x % num[j] is rem[j]
    19. # or not (for all j from
    20. # 0 to k-1)
    21. j = 0;
    22. while(j < k):
    23. if (x % num[j] != rem[j]):
    24. break;
    25. j += 1;
    26. # If all remainders
    27. # matched, we found x
    28. if (j == k):
    29. return x;
    30. # Else try next number
    31. x += 1;
    32. # Driver Code
    33. num = [3, 4, 5];
    34. rem = [2, 3, 1];
    35. k = len(num);
    36. print("x is", findMinX(num, rem, k));

    (4)c#

    1. using System;
    2. class ZGYSDL
    3. {
    4. // k is size of num[] and rem[].
    5. // Returns the smallest
    6. // number x such that:
    7. // x % num[0] = rem[0],
    8. // x % num[1] = rem[1],
    9. // ..................
    10. // x % num[k-2] = rem[k-1]
    11. // Assumption: Numbers in num[]
    12. // are pairwise coprime
    13. // (gcd for every pair is 1)
    14. static int findMinX(int []num, int []rem,
    15. int k)
    16. {
    17. // Initialize result
    18. int x = 1;
    19. // As per the Chinese remainder theorem,
    20. // this loop will always break.
    21. while (true)
    22. {
    23. // Check if remainder of x % num[j] is
    24. // rem[j] or not (for all j from 0 to k-1)
    25. int j;
    26. for (j = 0; j < k; j++ )
    27. if (x % num[j] != rem[j])
    28. break;
    29. // If all remainders matched, we found x
    30. if (j == k)
    31. return x;
    32. // Else try next number
    33. x++;
    34. }
    35. }
    36. public static void Main()
    37. {
    38. int []num = {3, 4, 5};
    39. int []rem = {2, 3, 1};
    40. int k = num.Length;
    41. Console.WriteLine("x is " + findMinX(num,
    42. rem, k));
    43. }
    44. }

    (5)php

    1. <?php
    2. // k is size of num[] and rem[].
    3. // Returns the smallest number x
    4. // such that:
    5. // x % num[0] = rem[0],
    6. // x % num[1] = rem[1],
    7. // ..................
    8. // x % num[k-2] = rem[k-1]
    9. // Assumption: Numbers in num[]
    10. // are pairwise coprime (gcd for
    11. // every pair is 1)
    12. function findMinX($num, $rem, $k)
    13. {
    14. $x = 1; // Initialize result
    15. // As per the Chinise remainder
    16. // theorem, this loop will
    17. // always break.
    18. while (true)
    19. {
    20. // Check if remainder of
    21. // x % num[j] is rem[j]
    22. // or not (for all j from
    23. // 0 to k-1)
    24. $j;
    25. for ($j = 0; $j < $k; $j++ )
    26. if ($x % $num[$j] != $rem[$j])
    27. break;
    28. // If all remainders
    29. // matched, we found x
    30. if ($j == $k)
    31. return $x;
    32. // Else try next number
    33. $x++;
    34. }
    35. return $x;
    36. }
    37. // Driver Code
    38. $num = array(3, 4, 5);
    39. $rem = array(2, 3, 1);
    40. $k = sizeof($num);
    41. echo "x is " ,
    42. findMinX($num, $rem, $k);
    43. ?>

    (6)javascript

    1. <script>
    2. // k is size of num and rem. Returns the smallest
    3. // number x such that:
    4. // x % num[0] = rem[0],
    5. // x % num[1] = rem[1],
    6. // ..................
    7. // x % num[k-2] = rem[k-1]
    8. // Assumption: Numbers in num are pairwise coprime
    9. // (gcd for every pair is 1)
    10. function findMinX(num , rem , k)
    11. {
    12. var x = 1; // Initialize result
    13. // As per the Chinese remainder theorem,
    14. // this loop will always break.
    15. while (true)
    16. {
    17. // Check if remainder of x % num[j] is
    18. // rem[j] or not (for all j from 0 to k-1)
    19. var j;
    20. for (j=0; j<k; j++ )
    21. if (x%num[j] != rem[j])
    22. break;
    23. // If all remainders matched, we found x
    24. if (j == k)
    25. return x;
    26. // Else try next number
    27. x++;
    28. }
    29. }
    30. // Driver method
    31. var num = [3, 4, 5];
    32. var rem = [2, 3, 1];
    33. var k = num.length;
    34. document.write("x is " + findMinX(num, rem, k));
    35. </script>

  • 相关阅读:
    c++game大全
    科技+智慧+颜值,智慧公厕黑科技提升城市形象
    openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化:x86
    用于包管理的基本命令APT-GET和APT-CACHE
    进军东南亚市场,腾讯云数据库 TDSQL 助力印尼 BNC 银行数字化转型
    Kalman滤波器的原理与实现
    【JVM】字节码技术:手撕 多态执行原理
    Vue3开始
    分布式ID(7):Zookeeper实现分布式ID生成
    Linux debian gdb dump
  • 原文地址:https://blog.csdn.net/bashendixie5/article/details/124974861