中国剩余定理-简明易懂

  中国剩余定理是一个耳熟能详的名字。我查找了百度百科上的解释,又四处寻找,但是真的每一篇都看不懂,看的我一头雾水。

  但是,通过不懈的寻找,终于在伟大的破站找到了看得懂的答案。这里将视频总结成我的语言,写在这里。

  这是20181109 23:18,Lightmain的第一篇博文。

《孙子算经》原题:

  韩信要点兵,让他的士兵站成三人一列,多出来两人;站成五人一列,多出来三人;站成七人一列,多两人。问共有多少人;

  可以通过枚举法:

  满足第一条:2,5,811,14,17,20,23,26,29....

  满足第二条:8,13,18,23,28......

  满足第三条:9,16,23,30......

  可以看出,23是同时满足三条的。然而,后面肯定会有重复的,怎么去求呢?要加上一个数n使其被3,5,7除的余数都不会变, 就要满足n是3,5,7的倍数,也就是nmin=105.所以,把23加上105i,使i取某一个整数就可以得到所有解了。然而,怎样把这个结论推广到所有的情况呢?

  这个所有数的最小公倍数很好求。问题主要出在23身上。我们的祖先想出了一个办法。他们还把这个办法变成一首诗:

  三人同行七十稀,五树梅花廿一支,七子团圆正半月,除百零五使得知。

  这个方法可以在3,5,7的情况下应对所有的余数关系。诗的意思是:对于三个一排的,把余数乘以70;对于五个一排的,余数乘以21;对于七个一排的,余数乘以15;加起来再减去一堆105。按照这个题,就是70*2+21*3+15*2 = 233,  233-105*2 = 23.所以这个是可以O(1)解的。

  容易看出:70是5,7的倍数,21是3,7的倍数,15是3,5的倍数,所以加上一个这样的数只会影响这个数关于其中一个数的余数。如:加上70之后,数字被7,5除的余数不会改变。

  有人有问题了:为什么第一个不是 35 而是 70 呢?原因是,这个数需要是5,7的倍数,还要除3余1,这样,每加了一个70,该数模3的余数就会加1,不然不能直接乘以余数。另外两个也是同理。

  所以,有了这个,就不难推广到所有情况了。

  对于两两互质的一组数A = {a1, a2, .... , an},要使得一个解x,对于所有的整数i∈[1,n], 同时满足 x%ai == mi(这个mi数组的每一个元素也是给定的且两两互质),就用这个方法。
  这里的A就相当于刚才每列站的3, 5, 7人,mi就相当于余下的2, 3, 2人,x就是我们求的总人数

  我们设M 为A数组所有元素的乘积。找出一个B数组,B = {b1, b2, .... , bn},  使得b是 M / ai 的倍数,而且bi%ai = 1.(L为任意整数)
  这里的B数组中的每一个数就相当于刚才的70, 21, 15。

  那么,我们就可以找到一个解:x0 = m1b1 + m2b2 + m3b3 ..... + mnbn.
  (233=70*2+21*3+15*2)

  要找到其他的解,就增加或减少s*t ,t为随意的一个整数。

  于是,中国剩余定理恆錓傗釶(HengKongChuShi)了。

  然而,还有一个问题。怎么求B?

  B的唯一定义是b是 M / ai 的倍数,而且bi%ai = 1.
  因为有倍数关系,所以设 bi = (M/ai) * k. 而  bi%ai = 1  写得规范一点就是下面这个式子:

   (M/ai) * k ≡ 1(mod ai)    求k。

  把它转化为正常的方程。当然是不定方程。

    (M/ai) * k + ai * j = 1 。

  因为A两两互质,M是A中所有数的乘积,所以(M/ai)与ai互质。所以用扩展欧几里得解就可以了。

  代码就不给了,反正也没有几个人耐得下性子看,还不如回去自己写。

  就此㝴㸅(wan jie)!

posted @ 2019-04-13 13:41  lightmain  阅读(1052)  评论(1编辑  收藏  举报