夜深人静写算法(三十六)- 中国剩余定理
Posted 英雄哪里出来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了夜深人静写算法(三十六)- 中国剩余定理相关的知识,希望对你有一定的参考价值。
📢博客主页:https://blog.csdn.net/WhereIsHeroFrom
📢欢迎各位 👍点赞 ⭐收藏 📝评论,如有错误请留言指正,非常感谢!
📢本文由 英雄哪里出来 原创,转载请注明出处,首发于 🙉 CSDN 🙉
作者的专栏:
👉C语言基础专栏《光天化日学C语言》
👉C语言基础配套试题《C试题100例》
👉算法进阶专栏《夜深人静写算法》
文章目录
一、前言
当初学这个算法,纯粹是因为她叫 —— * * 剩余定理(那两个字发出来竟然被判定违规了,阿这……)。所以我们只能叫它的另一个名字 —— 孙子定理。有兴趣的朋友可以自行百度它原本的名字。
二、 物不知数
1、引例
【例题1】有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?
- 这个问题是中国南北朝时期的数学著作《孙子算经》卷下第二十六题,叫做 “物不知数” 问题,这个问题翻译成现代文的意思是:一个整数除以三余二,除以五余三,除以七余二,求这个整数。
- 表示如下:
- ( S ) : { x ≡ 2 ( m o d 3 ) x ≡ 3 ( m o d 5 ) x ≡ 2 ( m o d 7 ) (S): \\begin{cases}x \\equiv 2(mod \\ 3)\\\\ x \\equiv 3(mod \\ 5)\\\\ x \\equiv 2(mod \\ 7) \\end{cases} (S):⎩⎪⎨⎪⎧x≡2(mod 3)x≡3(mod 5)x≡2(mod 7)
- 由于每一行都是一个同余方程,其中 x x x 是公共的未知数。
- 用这样的形式表示的我们称它为同余方程组,
S
S
S 就是这个同余方程组。
三、同余方程组
- 我们将同余方程表示成更加一般的形式,如下:
- ( S ) : { x ≡ a 1 ( m o d m 1 ) x ≡ a 2 ( m o d m 2 ) ⋮ x ≡ a n ( m o d m n ) (S): \\begin{cases}x &\\equiv a_1(mod \\ m_1)\\\\ x &\\equiv a_2(mod \\ m_2)\\\\ &\\vdots \\\\ x &\\equiv a_n(mod \\ m_n) \\end{cases} (S):⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧xxx≡a1(mod m1)≡a2(mod m2)⋮≡an(mod mn)
- 我们知道同余方程是可以表示成等式的形式的,那么同余方程组自然也可以,我们可以这么来表示:
- ( S ) : { x = k 1 m 1 + a 1 x = k 2 m 2 + a 2 ⋮ x = k n m n + a n ( k i ∈ Z ) (S): \\begin{cases}x &= k_1m_1 + a_1\\\\ x &= k_2m_2 + a_2\\\\ &\\vdots \\\\ x &= k_nm_n + a_n\\end{cases} \\\\ \\\\ (k_i \\in Z) (S):⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧xxx=k1m1+a1=k2m2+a2⋮=knmn+an(ki∈Z)
- n n n 个方程, n + 1 n+1 n+1 个未知数的情况下,解的情况可能存在,也可能不存在,存在的情只可能是无穷多解。
1、不存在解
- 这种情况比较好理解,当存在 i i i 和 j j j,同时满足 m i = m j m_i=m_j mi=mj 且 a i ≠ a j a_i \\neq a_j ai=aj 时,解必然是不存在的。
- 因为任何一个数模另外一个数,得到的结果一定是确定的,不可能有两种结果。
2、存在无穷多解
- 一旦存在解,那么对于任意两个 i i i 和 j j j,只要 m i = m j m_i=m_j mi=mj ,必然满足 a i = a j a_i = a_j ai=aj,出现这种情况时,变量数和方程数同时减少。
- 换言之,未知数永远比方程数多 1,这样就一定有无穷多解了。
四、朴素算法
1、模数互素
- 朴素算法就是穷举,以 “物不知数” 问题为例,我们可以从零开始枚举 x x x 的值。然后不断试除,看什么时候能够满足三个同余方程同时成立。
- ( S ) : { x ≡ 2 ( m o d 3 ) x ≡ 3 ( m o d 5 ) x ≡ 2 ( m o d 7 ) (S): \\begin{cases}x \\equiv 2(mod \\ 3)\\\\ x \\equiv 3(mod \\ 5)\\\\ x \\equiv 2(mod \\ 7) \\end{cases} (S):⎩⎪⎨⎪⎧x≡2(mod 3)x≡3(mod 5)x≡2(mod 7)
- 代码实现如下:
#include <iostream>
using namespace std;
const int MAXN = 3;
int m[MAXN] = {3, 5, 7};
int a[MAXN] = {2, 3, 2};
int main() {
for(int x = 0; x < 400; ++x) { // (1)
bool bfind = true;
for(int i = 0; i < MAXN; ++i) {
if( x % m[i] != a[i] ) { // (2)
bfind = false;
break;
}
}
if(bfind) {
printf("%d\\n", x); // (3)
}
}
return 0;
}
- ( 1 ) (1) (1) 由于解有无数个,所以为了输出的时候能够观测到一些规律,我们只输出小于 400 的解。
- ( 2 ) (2) (2) 对于每个 ( m i , a i ) (m_i, a_i) (mi,ai) 的整数对,用枚举得到的 x x x 进行试除,看能否整除,一旦不满足就跳出循环;
-
(
3
)
(3)
以上是关于夜深人静写算法(三十六)- 中国剩余定理的主要内容,如果未能解决你的问题,请参考以下文章