在《孙子算经》中有这样一个问题:有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?
这个问题说的是,有一件物品,我们不知道它的数量。但是,如果三个三个数,最后会剩下两个;如果五个五个数,最后会剩下三个;如果七个七个数,最后会剩下两个。问这个东西的数量是多少?
实际上,这个问题在现在我们可以将其转化为一个同余方程组:
中国剩余定理告诉了我们像这样的同余方程组的解。这个定理又称为孙子定理,通常被简写成CRT
这篇文章将会从欧几里得算法开始讲起,之后过渡到扩展欧几里得算法解线性方程,最后介绍中国剩余定理。
欧几里得算法
欧几里得算法是用来计算最大公约数的一个算法,它主要是基于下面这个递归式:
gcd(n,m)=gcd( m ,n mod m)
如果这个式子成立的话,不断的利用这个式子来计算,直到n和m中有一个数变成0的时候,就可以求出了他们的最大公约数。
我来举个例子来说,比如我们要求6和15的最大公约数,那么利用前面的式子就可以得到
gcd(6,15)=gcd(15,6)=gcd(6,3)=gcd(3,0)=3
那么如何证明这个式子呢?
我们可以设g=gcd(n,m),这样的话,对于右边的部分,g | m是显然的,至于g | (n mod m)是否成立,我们可以根据
得出肯定的答案。这样我们就可以得到g | gcd(m , n mod m).
同样的,如果设 gx = gcd(m , n mod m) ,那么也可以得到 gx | g 。这样再根据整除关系的传递性,就可以得到 g | gx | g。因此g和gx必定相等。
int gcd(int n,int m)
{
if(m==0) return n;
return gcd(m,n%m);
}
裴蜀定理
假设我们有一个关于x和y的线性方程 ax + by = d,现在要求判断这个方程是否存在整数解。
裴蜀定理告诉我们,ax + by = d存在整数解当前仅当 gcd ( a , b ) | d 。例如说3x + 6y = 2就不存在整数解,3x + 6y = 3就存在整数解 x =1 ,y = 0 。
如何证明?显然gcd( a , b) | (ax + by),如果存在整数的解的话必然有 gcd ( a , b ) | d 。
那么在gcd( a, b) | d的时候一定都存在整数解吗?我们来通过扩展欧几里得算法解释这个问题,实际上,扩展欧几里得的算法不仅回答了这个问题,而且还把解构造了出来。
扩展欧几里得算法
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1,y=0;
return a;
}
int g=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return g;
}
中国剩余定理
我们先来考虑只有两个方程,并且模数互质的情况。假设现在有一个关于x的同余方程组:
我们如何解这个方程组呢?按照同余式的定义,我们知道上面这个方程组等价于
其中k1,k2是整数。我们现在可以把(1)中的两个方程联立起来,再消去x。这样就会得到一个二元一次方程: