关于韩信点兵的算法以及原理

来源:互联网 发布:淘宝确认收货 花呗 编辑:程序博客网 时间:2024/06/18 09:24
描述
相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入3个非负整数a,b,c ,表示每种队形排尾的人数(a<3,b<5,c<7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100 。
输入
输入3个非负整数a,b,c ,表示每种队形排尾的人数(a<3,b<5,c<7)。例如,输入:2 4 5
输出
输出总人数的最小值(或报告无解,即输出No answer)。实例,输出:89
样例输入
2 1 6
样例输出

41

思考来源于这么一道简单的ACM题

因为总人数为10到100之间,数据量较小,可以暴力求解。

但经了解,韩信点兵是一种很有趣的算法

在一千多年前的《孙子算经》中,有这样一道算术题:
“今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问物几何?”按照今天的话来说:一个数除以3余2,除以5余3,除以7余2,求这个数.
这样的问题,也有人称为“韩信点兵”.它形成了一类问题,也就是初等数论中解同余式.这类问题的有解条件和解的方法被称为“中国剩余定理”,这是由中国人首先提出的.

我国古代学者早就研究过这个问题。例如我国明朝数学家程大位在他著的《算法统宗》(1593年)中就用四句很通俗的口诀暗示了此题的解法:

三人同行七十稀,

五树梅花甘一枝,

七子团圆正半月,

除百零五便得知。

"正半月"暗指15。"除百零五"的原意是,当所得的数比105大时,就105、105地往下减,使之小于105;这相当于用105去除,求出余数。

这四句口诀暗示的意思是:当除数分别是3、5、7时,用70乘以用3除的余数,用21乘以用5除的余数,用15乘以用7除的余数,然后把这三个乘积相加。加得的结果如果比105大,就除以105,所得的余数就是满足题目要求的最小正整数解。

按这四句口诀暗示的方法计算韩信点的这队士兵的人数可得:

70×2+21×3+15×4=263,

263=2×105+53,

所以,这队士兵至少有53人。

在这种方法里,我们看到:70、21、15这三个数很重要,稍加研究,可以发现它们的特点是:

70是5与7的倍数,而用3除余1;

21是3与7的倍数,而用5除余1;

15是3与5的倍数,而用7除余1。

因而

70×2是5与7的倍数,用3除余2;

21×3是3与7的倍数,用5除余3;

15×4是3与5的倍数,用7除余4。

如果一个数除以a余数为b,那么给这个数加上a的一个倍数以后再除以a,余数仍然是b。所以,把70×2、21×3与15×4都加起来所得的结果能同时满足"用3除余2、用5除余3、用7除余4"的要求。一般地,

70m+21n+15k (1≤m<3, 1≤n<5,1≤k<7)

能同时满足"用3除余m 、用5除余n 、用7除余k"的要求。除以105(因为105是3、5、7三数的最小公倍数)取余数,是为了求合乎题意的最小正整数解。

我们已经知道了70、21、15这三个数的性质和用处,那么,是怎么把它们找到的呢?要是换了一个题目,三个除数不再是3、5、7,应该怎样去求出类似的有用的数呢?

为了求出是5与7的倍数而用3除余1的数,我们看看5与7的最小公倍数是否合乎要求。5与7的最小公倍数是5×7=35,35除以3余2,35的2倍除以3余2,35的2倍除以3就能余1了,于是我们得到了"三人同行七十稀"。
为了求出是3与7的倍数而用5除余1的数,我们看看3与7的最小公倍数是否合乎要求。3与7的最小公倍数是3×7=21,21除以5恰好余1,于是我们得到了"五树梅花甘一枝"。
为了求出是3与5的倍数而用7除余1的数,我们看看3与5的最小公倍数是否合乎要求。3与5的最小公倍数是3×5=15,15除以7恰好余1,因而我们得到了"七子团圆正半月"。
3、5、7的最小公倍数是105,所以"除百零五便得知"。

例如:试求一数,使之用4除余3,用5除余2,用7除余5。
解:我们先求是5与7的倍数而用4除余1的数;5与7的最小公倍数是5×7=35,35除以4余3,3×3除以4余1,因而35×3=105除以4余1,105是5与7的倍数而用4除余1的数。
我们再求4与7的倍数而用5除余1的数;4与7的最小公倍数是4×7=28,28除以5余3,3×7除以5余1,因而28×7=196除余5余1,所以196是4与7的倍数而用5除余1的数。
最后求的是4与5的倍数而用7除余1的数:4与5的最小公倍数是4×5=20,20除以7余6,6×6除以7余1,因而20×6=120除以7余1,所以120是4与5的倍数而用7除余1的数。
利用105、196、120这三个数可以求出符合题目要求的解:
105×3+196×2+120×5=1307。
由于4、5、7的最小公倍数是4×5×7=140,1307大于140,所以1307不是合乎题目要求的最小的解。用1037除以140得到的余数是47,47是合乎题目的最小的正整数解。

一般地,
105m+196n+120k (1≤m<4,1≤n<5,1≤k<7)
是用4除余m,用5除余n,用7除余k的数(105m+196n+120k)除以140所得的余数是满足上面三个条件的最小的正数。
上面我们是为了写出105m+196n+120k这个一般表达式才求出了105这个特征数。如果只是为了解答我们这个具体的例题,由于5×7=35既是5与7的倍数除以4又余3,就不必求出105再乘以3了。
35+196×2+120×5=1027
就是符合题意的数。
1027=7×140+47,
由此也可以得出符合题意的最小正整数解47。

《算法统宗》中把在以3、5、7为除数"物不知其数"问题中起重要作用的70、21、15这几个特征数用几句口诀表达出来了,我们也可以把在以4、5、7为除数的问题中起重要作用的105、196、120这几个特征数编为口诀。留给读者自己去编吧。
凡是三个除数两两互质的情况,都可以用上面的方法求解。
上面的方法所依据的理论,在中国称之为孙子定理,国外的书籍称之为中国剩余定理。