偶然发现一道小学奥数题,题目如下:

老师给全班同学排队,每3个人站一排,最后一排只有2个人;每5个人站一排,最后一排为3个人;每7个人站一排,最后一排为2个人,请问全班最少多少名同学?

此题看似一般,但经查阅,却极有渊源,原来题目源于《孙子算经》,此书著于南北朝时期,作者不详,与春秋时期《孙子兵法》的作者并非一人。

目录

一、《孙子算经》之“物不知数”

1、原文及译文

2、计算公式

3、剩余定理

二、规律探索

1、《孙子歌诀》

2、表格解析

(1)最小公倍数105的解析

(2)除7的余数对应系数15的解析

(3)除5的余数对应系数21的解析

(4)除3的余数对应系数70的解析

(5)《孙子算经》“不知其数”结果分析

三、为什么要研究算法

1、效率最低的算法

2、高级一点的算法

3、孙子算经算法


一、《孙子算经》之“物不知数”

1、原文及译文

《孙子算经》卷下第二十六题“物不知数”原文如下:

今有物,不知其数。三三数之,剩二;五五数之,剩三;七七数之,剩二。问:物几 何?

答曰:二十三。

术曰:三三数之,剩二,置一百四十;五五数之,剩三,置六十三;七七数之,剩二 ,置三十。并之,得二百三十三,以二百一十减之,即得。凡三三数之,剩一,则置七十 ;五五数之,剩一,则置二十一;七七数之,剩一,则置十五。一百六以上,以一百五 减之,即得。

“物不知数”的译文如下:

现有一些物品,具体数目不详。3个3个数,最后剩2个;5个5个数,最后剩3个;7个7个数,最后剩2个,问这些物品多少个?

答案:23个

解题思路:3个3个数,余数是2,余数乘以70等于140;5个5个数,余数是3,余数乘以21等于63;7个7个数,余数2,余数乘以15等于30。把以上三个得数加起来就是140+63+30=233。这个数大于3*5*7的最小公倍数105,所以要减去若干次105直到小于105为止,经过减两次105共210,得出答案:233-210=23。解题规律:3个3个数,用其余数乘以70;5个5个数,用其余数乘以21;7个7个数,用其余数乘以15;再把三个得数相加起来,如果得数大于等于106,那么就减去若干次105,直到小于105,就是正确答案。

2、计算公式

根据孙子算经得出计算得公式为:被除数=除3余数×70+除5余数×21+除7余数×15,如果大于105,则减若干次105,直至小于105时为止,得到的那个数就是正确答案。

注意:“不知其数”原文中省略了是符合条件的最小数,本文以下介绍的内容,也默认是符合条件的最小数。

3、剩余定理

“物不知数”文中不但给出了题目、答案,还给出了解题的技巧和规律。宋朝数学家秦九韶于1247年《数书九章》卷一、二《大衍类》对“物不知数”问题做出了完整系统的解答,进一步开创了对一次同余式理论的研究工作,推广了“”。德国数学家高斯于公元1801年出版的《算术探究》中明确地写出了上述定理。公元1852年,英国基督教士伟烈亚士将《孙子算经》“物不知数”问题的解法传到欧洲,公元1874年马蒂生[L.Mathiesen]指出孙子的解法符合高斯的定理,从而在西方的数学史里将这一个定理称为“中国的剩余定理”[Chinese remainder theorem]。

下图是用现代数学语言来解决“物不知数”问题的解题公式:

二、规律探索

利用现代数学方法,可以推导出此公式,那么早在1500年前,我国古人又是怎么发现此问题的解题规律的呢?下面,小编就用列表法尝试着推测一下古人的解题思路。

1、《孙子歌诀》

仔细研读“物不知数”的解题思路发现,这道题的解题关键是发现了3个3个数、5个5个数、7个7个数的余数要乘的那3个系数70、21、15,和周期数105。明朝数学家程大位将解法规律所确定的这四个数编成易于上口的《孙子歌诀》:
三人同行七十稀,五树梅花廿一支,七子团圆正半月,除百零五使得知。

那么这四个数是怎么发现的呢?

2、利用列表法分析

(1)最小公倍数105的分析

下边先看表1,列出了被除数从0到105时,除数为3、5、7所对应的余数。那么被除数为0和105时余数都为0,从106开始又是和1是一样的,所以规律的周期就是105。也就是互质数3、5、7的最小公倍数。

表1 余数总表

被除数 除数为3 除数为5 除数为7
0 0 0 0
1 1 1 1
2 2 2 2
3 0 3 3
4 1 4 4
5 2 0 5
6 0 1 6
7 1 2 0
8 2 3 1
9 0 4 2
10 1 0 3
11 2 1 4
12 0 2 5
13 1 3 6
14 2 4 0
15 0 0 1
16 1 1 2
17 2 2 3
18 0 3 4
19 1 4 5
20 2 0 6
21 0 1 0
22 1 2 1
23 2 3 2
24 0 4 3
25 1 0 4
26 2 1 5
27 0 2 6
28 1 3 0
29 2 4 1
30 0 0 2
31 1 1 3
32 2 2 4
33 0 3 5
34 1 4 6
35 2 0 0
36 0 1 1
37 1 2 2
38 2 3 3
39 0 4 4
40 1 0 5
41 2 1 6
42 0 2 0
43 1 3 1
44 2 4 2
45 0 0 3
46 1 1 4
47 2 2 5
48 0 3 6
49 1 4 0
50 2 0 1
51 0 1 2
52 1 2 3
53 2 3 4
54 0 4 5
55 1 0 6
56 2 1 0
57 0 2 1
58 1 3 2
59 2 4 3
60 0 0 4
61 1 1 5
62 2 2 6
63 0 3 0
64 1 4 1
65 2 0 2
66 0 1 3
67 1 2 4
68 2 3 5
69 0 4 6
70 1 0 0
71 2 1 1
72 0 2 2
73 1 3 3
74 2 4 4
75 0 0 5
76 1 1 6
77 2 2 0
78 0 3 1
79 1 4 2
80 2 0 3
81 0 1 4
82 1 2 5
83 2 3 6
84 0 4 0
85 1 0 1
86 2 1 2
87 0 2 3
88 1 3 4
89 2 4 5
90 0 0 6
91 1 1 0
92 2 2 1
93 0 3 2
94 1 4 3
95 2 0 4
96 0 1 5
97 1 2 6
98 2 3 0
99 0 4 1
100 1 0 2
101 2 1 3
102 0 2 4
103 1 3 5
104 2 4 6
105 0 0 0

从表1可以看出,根据三个余数,就可以找到对应的被除数。那么我们不可能去每给出一组余数,我们就去查一次表,我们需要去寻找这个被除数和每组余数之间的规律,根据规律来快速计算出结果。寻找规律要由最简单的情形开始,当两个除数的对应余数是固定的且都为0时,看看第三个除数对应的余数依次增加1时的规律。

(2)除7的余数对应系数15的解析

假如当除3、除5的余数都是0时,当除7余数以步伐为1从0递增到6时,我们来看看被除数有什么变化规律?从表1中筛选出除3余0并且除5余0的情况如表2所示。

表2  除3余0且除5余0表

被除数 除数为3 除数为5 除数为7
0 0 0 0
15 0 0 1
30 0 0 2
45 0 0 3
60 0 0 4
75 0 0 5
90 0 0 6

从表2可以看出,搜出数据一共7行,正好对应余数从0到6,而且余数是依次加1的。除7余0对应的被除数为0,除7余1对应的被除数为15,除7余2对应的被除数为30,……,依次增加15!这就是除7余数对应的系数为15的原因,且15=3*5,为除数7之外的两个除数最小公倍数。

(3)除5的余数对应系数21的解析

同样,假如当除3、除7的余数都是0,当除5余数每增加1时,我们来看看被除数有什么变化规律?从表1中筛选出除3余0并且除7余0的情况如表3所示。

表3  除3余0并且除7余0表

被除数 除数为3 除数为5 除数为7
0 0 0 0
21 0 1 0
42 0 2 0
63 0 3 0
84 0 4 0

从表3可以看出,搜出数据一共5行,正好对应余数从0到4,而且余数是依次加1的。除5余0对应的被除数为0,除5余1对应的被除数为21,除5余2对应的被除数为42,……,依次增加21!这就是除5余数对应的系数为21的原因,且21=3*7,为除数5之外的两个除数最小公倍数。

(4)除3的余数对应系数70的解析

同样,假如当除5、除7的余数都是0,当除3余数每增加1时,我们来看看被除数有什么变化规律?从表1中筛选出除5余0并且除7余0的情况如表4所示。

表4  除5余0并且除7余0表

被除数 除数为3 除数为5 除数为7
0 0 0 0
35 2 0 0
70 1 0 0

从表4可以看出,搜出数据一共3行,正好对应余数从0到2,每行的被除数增值为35。但是余数却不是依次加1,而是0、2、1,从0到1跨过了2,也就是从0到1被除数增值为70!这条规律与前两条是不同的。这就是除3余数对应的系数为70的原因。

为了更清楚地看出规律,我们从两个周期210个被除数中搜索除5余0、除7余0的情况,如表5所示,除数为3所在列第一行余数为0,被除数为0;第三行余数为1,被除数为70;第五行余数为2,被除数为140。除3列余数的规律为隔行增加1,余数0、1对应的被除数在第一个周期105以内,而余数2对应的被除数是在下一个周期105-210之内。这也就是为什么会出现计算结果大于105的原因

表5  除5余0并且除7余0两个周期表

被除数 除数为3 除数为5 除数为7
0 0 0 0
35 2 0 0
70 1 0 0
105 0 0 0
140 2 0 0
175 1 0 0

(5)《孙子算经》“不知其数”结果分析

按着“不知其数”的题目,我们以除3余2,除5余3,除7余2为例进行分析。

按照公式,计算结果如下:

被除数=2×70+3×21+2×15=233,233-105=128,128-105=23。

减了两次105,才得出结果,那么还用列表来分析一下,为什么会减两次。

(a)先看当除3余2且除5余3时,除7余数的两个周期的规律如表6所示,余数为2在两个周期都出现了,那么哪一个才是正确的那个呢?

下边给出一条定律(暂称爬爬虫定律1):余数为0所在的第一行为起始行,其后依次出现的1、2、3……对应的行所在的周期就是被除数所在最小周期。

根据以上定律,除数为7的余数一共有两个周期,余数为0的起始位是在第7行,其后的余数1在第8行,余数1之后的余数2在第9行,对应的被除数为128,在区间[105,210]内,属于第二个周期。所以按照除7列,计算结果所在最小的周期为第二个周期。

表6  除3余2且除5余3两个周期表

被除数 除数为3 除数为5 除数为7
8 2 3 1
23 2 3 2
38 2 3 3
53 2 3 4
68 2 3 5
83 2 3 6
98 2 3 0
113 2 3 1
128 2 3 2
143 2 3 3
158 2 3 4
173 2 3 5
188 2 3 6
203 2 3 0

(b)再看当除3余2且除7余2时,除5余数的两个周期的规律如表7所示,余数为3在两个周期都出现了,那么哪一个才是正确的那个呢?

表7  除3余2且除7余2两个周期表

被除数 除数为3 除数为5 除数为7
2 2 2 2
23 2 3 2
44 2 4 2
65 2 0 2
86 2 1 2
107 2 2 2
128 2 3 2
149 2 4 2
170 2 0 2
191 2 1 2

根据爬爬虫定律1,先找到余数0所在行,为第4行,然后依次找到余数1、2、3所在的行分别为5、6、7,第7行对应的被除数为128,在[105,210]之间,属于第二个周期。所以按照除5列,计算结果也在第二个周期。

(c)最后看当除5余3且除7余2时,除3余数的三个周期的规律如表8所示,余数为2在三个周期都出现了,那么哪一个才是正确的那个呢?

表8  除5余3且除7余2三个周期表

被除数 除数为3 除数为5 除数为7
23 2 3 2
58 1 3 2
93 0 3 2
128 2 3 2
163 1 3 2
198 0 3 2
233 2 3 2
268 1 3 2
303 0 3 2

根据爬爬虫定律1,先找到余数0所在的起始行为第3行,其后的余数1在第5行,余数1之后的余数2在第7行,该行对应的被除数为233,在区间[210,315]之内,属于第三个周期。所以按照除3列,计算结果在第三个周期。

那么问题又来了,按照除7列,计算结果在第二周期,按照除5列,计算结果在第二周期,按照除3列,计算结果在第三周期。那么到底是在第二周期还是第三周期呢?

爬爬虫定律2:被除数所在周期为所有除数列计算出的周期中的最大周期。

根据爬爬虫定律2,第三周期为最大周期,也就是最终计算结果落在第三周期,那么105以内的最小值就是在计算结果上减去两个周期,即233-2×105=33。

至此,用列表法圆满解释了《孙子算经》之“不知其数”问题的三个系数、最小公倍数和计算结果减去周期个数的规律。

三、为什么要研究算法

有人说:“现在都有计算机了,还搞那么复杂干啥,你花了好几天时间,写了一大堆,还不如花几分钟时间写个程序计算一下,又快又准。”于是呼呼呼,写出了以下代码:

1、效率最低的算法

#include <stdio.h>
#include <string.h>int main()
{int r3,r5,r7,d,i;scanf("%d %d %d",&r3,&r5,&r7); for(i=0;i<105;i++){d=i;if((i % 7)==r7) && (i % 5)==r5 && (i % 3)==r3)break;} printf("所求的数为:%d\n",d); return d;
}

这种遍历的方法确实能算出答案,但效率太低,最多需要105+15+3=123步计算,说是算出来的,不如说是比对出来的,严格来说,都不能叫算法。

2、高级一点的算法

#include <stdio.h>
#include <string.h>int main()
{int r3,r5,r7,d,i,j;    scanf("%d %d %d",&r3,&r5,&r7); j=0;for(i=0;i<15;i++){d=i*7+r7;if((d % 5)==r5){j++;if((d % 3)==r3){break;}}} printf("所求的数为:%d\n",d); printf("计算步数为:%d\n",(i+1)*2+j); return d;
}

这种算法只在符合除7余数的15个数字中进行比对,最多计算步数:15+15+3=33步,步数降低很多,但代码又变复杂了。

3、孙子算经算法

#include <stdio.h>
#include <string.h>int main()
{int r3,r5,r7,d,i;   scanf("%d %d %d",&r3,&r5,&r7); i=0;d=r3*70+r5*21+r7*15;while(d>105){i++;d=d-105;} printf("所求的数为:%d\n",d); printf("计算步数为:%d\n",i+1); return d;
}

这种算法代码量最少,最多计算步数:1+2=3步,也是最少。

三种算法,孰优孰劣,一目了然。尽可能用最少的开支完成更多的计算量,让计算机系统更加高效工作,这就是研究算法的目的所在吧。

文章中如有谬误之处,拜请各路大神指正。

题外话:虽然现在IT行业,无论硬件的控制器芯片,还是软件类的开发平台,还是各种协议标准,还是各类主流算法都是欧美主导,我们还处于学习和追赶阶段。但很多经典算法其实也是源于古代数学思维,而我国古代有很多出色的数学家如刘徽、赵爽、杨辉、祖冲之、贾宪、秦九韶、朱世杰、徐光启等,和许多著名数学论著,如《周髀算经》、《九章算术》、《海岛算经》、《五曹算经》、《孙子算经》、《夏侯阳算经》、《张丘建算经》、《五经算术》、《缉古算经》、《缀术》等等。而六爻八卦、天干地支、阴阳五行也都包含着十分丰富的逻辑思维,能从现代算法中看到古代逻辑思维的影子。无论世界如何变,我中华传统文化都是一座取之不尽用之不竭的宝库,而我辈也当继承发扬之。我们在科学技术上的落后,也只是从近现代开始的。所以我们不能盲目排外,但也没必要一味媚外,丧失了文化自信、科学自信和技术自信。使用外来的先进技术,目的是为我所用,促进自己技术进步,而不能因为用惯了别人的,就丧失了自我发展的动力和能力。我们的老祖宗能做到领先世界几百年上千年,我想我们也应该有这个决心和动力。

用列表法分析1500年前南北朝时期的“奥数”题相关推荐

  1. 东汉魏晋南北朝时期职业教徒的阶层分析

    王青 刊<中国史研究>1997年第1期,转自象牙塔 马克斯·韦伯(Max Weber)通过对世界宗教的研究后得出结论:在社会地位与对不同宗教世界观的接受倾向之间,有着一种显而易见的明确的联 ...

  2. 小学生到底要不要学奥数 学奥数的利弊分析!

    小学生到底要不要学奥数?这个颇受争议的话题困扰着很多家长,作为一个从事数学教育多年的老师,我认为学习奥数没有所谓的该不该学,而是作为家长你想让孩子学习奥数的目的是什么?还有一个很重要的点是孩子是否愿意 ...

  3. 力扣242.有效的字母异位词(Java语言,排序法、散列表法)

    题目描述: 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词. 注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词. 解题思路: 思路1: ...

  4. 射频毫米波芯片设计11:基于奇偶模法分析设计射频微波Wilkinson功分器

    <射频微波芯片设计>专栏适用于具备一定微波基础知识的高校学生.在职射频工程师.高校研究所研究人员,通过本系列文章掌握射频到毫米波的芯片设计流程,设计方法,设计要点以及最新的射频/毫米波前端 ...

  5. 圆周率 我国古代数学家对圆周率方面的研究工作,成绩是突出的。三国时期的刘徽、南北朝时期的祖冲之都在这个领域取得过辉煌战绩。

    /** 圆周率我国古代数学家对圆周率方面的研究工作,成绩是突出的.三国时期的刘徽.南北朝时期的祖冲之都在这个领域取得过辉煌战绩.有了计算机,圆周率的计算变得十分容易了.如今,人们创造了上百种方法求π的 ...

  6. 【运筹学】表上作业法 ( 最小元素法分析 | Vogel 方法 )

    文章目录 一." 最小元素法 " 分析 二.Vogel 方法 ( 差额法 ) 一." 最小元素法 " 分析 在上一篇博客 [运筹学]表上作业法 ( 求初始基可行 ...

  7. 微变等效电路法分析放大电路

    微变等效电路法分析放大电路 本文介绍的定义 一.简化的h参数微变等效电路 二.微变等效电路法应用 本文介绍的定义 微变等效电路法.h参数微变等效电路.单管共射放大电路的微变等效电路.Rbe近似估算.微 ...

  8. Case 2-1:用空间平滑法分析华南地区的TAI语地名分布

    Case 2-1:用空间平滑法分析华南地区的TAI语地名分布 本例研究华南地区TAI语地名分布,它采用了移动搜索法(FAC)和核估计两种空间平滑方法.移动搜索法(FCA)是以某点为中心画一个圆或正方形 ...

  9. 五步移相法matlab程序_用MATLAB软件对逆变电路移相调压进行仿真,30°,60°,90°的波形,并用分段分析法分析其原理_学小易找答案...

    [简答题]Translate the following ad into (1) a TV comercial, and (2) a factual introduction. Marie Franc ...

最新文章

  1. 来自mooon的最简单的日志类CSimpleLogger
  2. mysql 语音_MySQL 在各种程序语音的连接字符串(转)
  3. Python进阶07 函数对象
  4. 【SpringBoot】SpringBoot整合SpringDataJPA及基本使用
  5. 【Azure Show】|第三期 人工智能大咖与您分享!嘉宾陈海平胡浩陈堰平
  6. DDD理论学习系列(3)-- 限界上下文
  7. INTERNET的完整形式是什么?
  8. 第二十一期:拜托!面试不要再问我Spring Cloud底层原理
  9. linux内核剪裁 4412,itop4412开发板-Linux内核的编译
  10. 多库多事务降低数据不一致概率
  11. 测试鼠标点击速度软件编程,怎么测试鼠标自动点击速度
  12. 密码学中的各类密码汇总(一)
  13. Exadata通过ILOM远程MOUNT ISO实现刷机Reimage
  14. shell中变量截取
  15. 技术沙龙之IOS相机管理
  16. 解决打开word很慢
  17. python pyplot bar 参数_数据可视化之条形图(1):Axes.bar
  18. 【钉钉-场景化能力包】会展入场
  19. 现代软件产品团队关键角色及职责简述
  20. sklearn数据集分割方法汇总

热门文章

  1. [培训-无线通信基础-3]:窄带无线信道(大小尺度衰落、多普勒效应)
  2. 超级计算机下,超级计算机app
  3. 实践出真知!7步搞懂分布式全内容,技术总监都拍手叫好
  4. 虚拟内存,分页与分段的区别、页面置换算法,颠簸,局部性原理
  5. 给学生补充的markdown 编辑器
  6. 微处理器件介绍:CPU/微控制器、DSP、FPGA、GPU
  7. 电脑密码忘记了怎么办?
  8. 为什么eolinker发送老是等待_eoLinker-AMS 开源版 常见问题
  9. java webclient使用_spring5 webclient使用指南详解
  10. SAP ABAP 使用内存参数设置SET /GET PARAMTER ID