中国剩余定理中间涉及一个重要观念:互质;
首先来看《孙子算经》卷下第二十六问:今有物,不知其数。三、三数之,剩二;五、五数之,剩三;七、七数之,剩二。问物几何?
转换为数学语言即是(理解其中的文言,三、三数之,不表示 /32 ,而是三个三个地,应当是 /3 ):
事实上(中国剩余定理的内容),不管物体总数除以3的余数,除以5的余数以及除以7(3、5、7互质)的余数分别为多少?在0到104( 3×5×7−1 )当中总存在唯一解,在此解(特解)的基础上再加上105的整数倍之后,可以得到其他所有的正整数解。这正是中国剩余定理:给出 m 个两两互质( 3,5,7,m=3 )的整数,它们的乘积为 P ( P=3×5×7=105 ),假设有一个未知数 M ( M=23 ),如果我们已知 M 分别除以这 M 个数所得的余数,那么在0到 P−1 的范围内,我们可以唯一地确定这个 M 。这可以看做是 M 的一个特解,其他所有满足要求的 M ,则正好是那些除以 P 之后余数等于这个特解的数( x≡M(modP)⇒x=nP+M )
我们回到《孙子算经》,来求解“今有物,不知其数”。根据中国剩余定理,由于除数3,5,7两两互质,因而解在0-104之间,且解唯一。我们求解的基本思路就是,依次找出满足每个条件,但是又不会破坏掉其他条件的数。
我们首先要寻找一个数,它既是5的倍数又是7的倍数,但同时除以3正好余2,也即 35⋅xmod3=2 ,根据 扩展欧几里得算法及其应用 一文的算法,我们可轻易对之求解,解得 x=1 ,也即该数为 35⋅x=35 ,
再来看第二个条件,寻找这么一个数,它既是3的倍数,又是7的倍数,同时除以5余3,也即 21⋅xmod5=3 ,此时解得, x=3 ,也即 21⋅x=63
同理对于第三个条件, 15⋅xmod7=2 ,解得 x=2 , 15⋅x=30
现在如果我们把 35,63,30 这三个数加在一起(得128)会怎样?它将同时满足题目中的三个条件。为了得一个0-104之间的解,我们在128的基础上减去 3×5×7=105 ,正好得到《孙子算经》当中的答案,23.
这是我们给出求解的 python 代码(因为涉及 a⋅xmodn=b 的求解,同样地我们也需给出扩展欧几里得算法的实现):
from operator import mul
from functools import reduce
def ext_euclid(a, b):
# ax + by = gcd(a, b)
if b == 0:
return (a, 1, 0)
d, x, y = ext_euclid(b, a%b)
return (d, y, x-a//b*y)
def mod_linear_equation(a, b, c):
d, x, y = ext_euclid(a, b)
if c%d:
raise 'no solution'
return x*(c//d)%b
def chinese_remainer(l1, l2):
# l1, l2 均为数组
# 分别表示除数,和余数
s = 0
P = reduce(mul, l1)
for i in range(len(l1)):
t = P//l1[i]
s += mod_linear_equation(t, l1[i], l2[i])*t
return s%P
if __name__ == '__main__':
print(chinese_remainer([3, 5, 7], [2, 3, 3]))
# 23