唐僧巧设水仙花数,悟空解题轻而易举
编程爱好者
第七回

上回讲到大数学家高斯解题妙法,下面,我们再见识两位中国古代的神话人物——孙悟空和唐僧。
据《大话西游》影片记载,唐僧西天取经路上三打了白骨精。白骨精最终被降服,由于她对悟空心生爱慕,不再为害人间,后来到大唐国开了一家饭馆。
唐僧和悟空西天取经回国后,经常到大街那边的白骨精饭馆去吃饭,时间长了,两人对白骨精好感日重。有一天悟空单独来到白家,说出了埋藏在心头多年的秘密:其实我打你三次确实无奈,唐老板老是在身后以紧箍咒相逼,并且你老是带一个号码是371的牌子,不打你,连老唐那边都不好骗呀?
白骨精笑着说:悟空哥哥,那是发生在战争年代的故事,我不会怪你的,不过,我说件事,你也不要生气。这个数字叫水仙花数,其实我带这个牌子是和老唐的一种约定,不然,他怎么知晓你是不是真心跟定他打工呢?
悟空听完心里打了个冷颤,一个问题也随之出现:水仙花数是哪几个数呢(水仙花数是一个三位数,其各位上数的立方和等于这个数,例如上面提到的371)?聪明的悟空稍加思考就获得了答案。悟空是如何做的呢?
唐僧水仙花数解析
水仙花数既然是一个三位数,那么它的范围也就再清楚不过了,100-999,所以总计有900种可能的情况,挺吓人的。让我们再读几遍老唐挑出的这个特殊号码——水仙花数,它有意思的地方是在数位和这个数之间建立了一种联系。怎样破解这种联系呢?
1.三位数和组成它的三个位
既然是三位数,可进行如下的假设,各数位从高到低分别是a、b、c,那么a、b、c和n之间有种一一对应关系。其实我们这里的问题也就成了知道某个数来拆分其数位了。三个数位拆分如下:
a=Int(n/100)
b=Int((n-100*a)/10)
c=n-100*a-b*10
要看900个数,可以先看一个数,先任意挑选一个数过来,如何看看它是不是水仙花数呢?
2.检查某个数是不是水仙花数
对于某个三位数,假设用n代表,只有两种可能,要么是水仙花数,要么不是。所以这个问题是个很简单的分支问题,问题分成了三部分:条件,条件成立时的工作,条件不成立时的工作。后面两部分最简单,只要输出相应信息就行,关键是如何塑造条件。
怎样判断这个数是不是水仙花数呢?条件就是“各位数的立方和等于这个数”。假设这个数是n,条件是个等式,条件中的后一部分很简单,前一部分是各个数位:
条件也就有了: n=a * a * a + b * b * b + c * c * c
但在使用前,还必须将a、b、c求出来。求出来的工作在1中我们已经做了。所以最终的N-S图也就成了图1。

3.900个数中哪些是水仙花数
一个数我们已经分析完成,两个数、900个数呢?
既然是这么有规则地一致,那何不用循环来完成(如图2示)。

将重复的部分放到一个循环里,问题解到此处,我们不禁为自己的聪明而叫绝。代码也就有了:
For i = 1 To 900
Input n
a = Int(n / 100) '拆分最高位
b = Int((n - 100 * a) / 10)'拆分10位
c = n - 100 * a - b * 10'拆分个位
If n = a * a * a + b * b * b + c * c * c Then
Print n ;” Shi ShuXianHuaShu”
else
Print n ;”BuShi ShuXianHuaShu”
End If
Next i
可当我们真刀真枪地在电脑上再试验的时候,又会吐血:怎么电脑老是要求往里输数,老也输不完(900遍啊)。电脑其实这时轻松地工作着,看着你笑:比比谁干得快!
我们和电脑比输入数字,太不值了,怎么办呢?唯一的答案是:我们的循环程序还要变。细看一下程序,输入的n值和循环变量i老是相差99,可不可以直接利用这个i呢,只要将input n 一句变换成n=i+99,问题不就成功解决了吗?
现在,我们可以喝着茶水,看电脑的把戏了。但屏幕上的东西会令我们的眼珠子不好用了,屏幕上显现的什么东西,900行啊,怎么我不需要的数字也给出现呢?所以,在“输出”中还需要调整,对我们有意义的是水仙花数,那些不是水仙花数的东西,就不要让他们出现在我们的面前吧!
几经周折,我们的源程序有了:
For n = 100 To 999
a = Int(n / 100) '拆分最高位
b = Int((n - 100 * a) / 10)'拆分10位
c = n - 100 * a - b * 10'拆分个位
If n = a * a * a + b * b * b + c * c * c Then
Print n '输出
End If
Next n
阿兰开讲
世上本没有循环,但重复的问题多了,就出现了循环。循环是我们破解现实问题的有力工具,循环结构程序的本质是顺序和分支,从这个意义上说,循环本质就是重复,但它又不是简单的一成不变的重复。使用循环,有三层境界。
第一层:重复的机械
处在此阶段的编程人员根本就不知道循环为何物,他们编程,就像打字员在打字。电脑嘲笑弱智的“打字员”,程序还没运行,但人已经被书写录入代码累得半死了。
第二层:机械的重复
此阶段的编程人员只知简单循环,不知变通。电脑嘲笑弱智的调试员,程序在执行着,我们以自己的弱势项目同电脑的优势项目火拼,那吃苦受累又不讨好的只能是人。
第三层:重复的变通
电脑是一台你的机器。以人的方式和它对话,但它以机器的方式工作着,人和电脑都找到自己的最爱。给人以人性化的关爱,给电脑以电脑化的关爱!
后面,我们还将继续寻找这些规律,欲知后事如何,且听下回分解。
小测验:车牌号码之谜
警察局的老K警员遇到了下面的一个难题,一辆卡车违反了交通规则,撞死了行人,司机畏罪驾车逃跑了。当时有3个人目击了这一车祸的发生,但都没有看清卡车的牌照号码,只注意到牌照号码的某些特征。
甲:记得牌照前两个数字是相同的;
乙:记得汽车号码的后两个数字是相同的;
丙:是一位数学家,他说:“牌照号码肯定是四位数,并且这个四位数恰好是一个整数的平方。”
根据这些线索,你能判断出正确的牌照号码吗?
上期小测验参考答案:
这类题目,其实是考察在限制条件下解决问题的能力。具体到这道题目来说,很多人往往认为应该由小明持灯来来去去,这样最节省时间,但最后却怎么也凑不出解决方案。但是换个思路,我们根据具体情况来决定谁持灯来去,只要稍稍做些变动即可:第一步,小明与弟弟过桥,小明回来,耗时4秒;第二步,小明与爸爸过河,弟弟回来,耗时9秒;第三步,妈妈与爷爷过河,小明回来,耗时13秒;最后,小明与弟弟过河,耗时4秒,总共耗时30秒,多么惊险!