求2011年(秋)江苏二级vb笔试部分填空题第四题解题过程要详细的,谢谢
Option Explicit Private Sub Cmd1_Click()
Dim n as integer, m as integer
M=135
N=8
Pic1.print fun(m,n)
Private Function fun(ByVal N As Integer,ByVal R As Integer)As string
dim L as integer
If N<R then
fun=N
Else
L=N\R
fun=fun(L,R)
fun=fun & N mod R
End if
pic1.print N
Exit Function 展开
你好,最近一段时间我比较忙,也没答题了。首先,不知道这是不是原题,因为有几个语法错误,不过既然是考题,我们就先不管语法错误了。先帮你解题,最后再说说语法错误。
递归问题的确是很容易迷糊的,其实做递归题,你可以把它类比成数学上的数列,或者更具体点就是数列的递推公式。
我做这道题,首先想把Cmd1_Click过程改掉,把m、n变量改成N、R变量,因为这样写更我们定义的fun函数中用的参数就是相同的字母了,而且因为这是2个过程中的变量,用相同的字母不属于重名,所以改成相同的字母更容易理清思路。
然后,我们可以试着翻译一下fun函数——把它直接翻译成数学语言有难度,我们可以先翻译成“伪代码”,就是:
ifN < R 那么,输出N
if N>=R 那么, L = N \ R,fun = fun(L, R),fun = fun & N Mod R,输出N
所以,我们看到,如果N<R,简单明了,输出个N就结束;但如果N>=R,我们就不知道需要递归多少次啦,但最后是在N<R时结束。
通过上边的分析,也得出个经验——做这样的题,一般是直接看最复杂的那两三条语句即可,所以我上边讲了这么多废话,就是希望你以后做这样的题,能一读题就能把上边的十几行程序看成是下边的3行:
L=N\R
fun=fun(L,R)
fun=fun & N mod R
其余是语句都是辅助性的!
同时,我相信你应该能达到这个要求,因为这道题就算是你一眼看到考的是这3句,也不一定能做出来——因为这道选择题综合性很高。(我们学校考的是C语言而不是VB,我不知道我这样评论是否正确,如果不对,希望以后看到的人指正)这里考到的递归,似乎很难写出数学公式,因为这个fun函数里有2个递归,还有运算符的优先级问题。
最“笨”也是最有效的办法就是带入计算,因为题目只问到前3行(事实上总共只输出了4行),是可以通过直接计算得到的。可问题是这里有2重递归,如果真要采用这个办法,我建议你先把剩余的题做完吧。
那就是说,我们把原题的10几行压缩到3行还不够——还要继续压缩,这3句里哪一句是直接参与运算的?很显然,只有“L=N\R”这一句,如果你能一读题,就发现除了这条语句,其余的都是“多余的”,这道题的结果就出来了!换句话说,只有这条语句才真正的进行运算的,如果把这句去掉,要么是死循环,要么输出的就是初始值和0、1等特殊值,而不是是一个有规律的“数列”。
所以,我们可以大胆猜测输出结果从最后一个到第1个应该是:
……
135
135\8
135\8\8
135\8\8\8
……
为什么是从后往前推测呢?因为递归运算是“先入后出”的,所以135这个初始值应该最后输出,按我们的猜测计算出来就是:
2
16
135
但我上边好像跟你说了句输出结果是4个值啊?——那是因为Com1_Click过程中还有个print语句,这不属于fun递归函数的一部分啊,而且恰好考题没问,因为第4个值没规律,问了就是考你数学啦,而不是考递归啊!所以,第4个输出值我们可以不予计算!
我们猜测的结果正确吗?我先告诉你一句,考场上如果没有时间,可以不验证,就按我们猜的填。(因为如果结果是没规律的,这是笔试,大家都不能上机调试,其他人算的肯定也不对)
怎样验证,按最直接的方法计算?太麻烦啦,真不建议你直接验证,我们最好找fun(4,2)这样的验证它的输出是否是:
2
4
如果是,那么原题的输出肯定是;
2
8
135
而且,考递归的题,笔试的话,最好是靠“猜”,而不是真的去计算,如果一道选择、填空都去计算,时间可能会不够用。怎么猜?核心语句是X=x^2,调用fun(3),就可以猜3、9、81……;核心语句是X=Y+Z,调用的是fun(1,1),就可以猜1,1,2,3,5,8……而我们需要验证的只是找个最简单的值带入,看看初始值和结束值是几,然后填上就行。万一错了,那也没办法,因为如果你把它按大题做,你丢的分会更多。
如果你一定要弄清楚原题的正规的做法,我认为需要上机调试,我给你把那3句分别加上A、B、C3个标签,然后你自己分析具体是怎么递归的。因为,一来我不想让你按这个方法一步步计算;二来我讲也是照着这个调试程序讲,而笔试不能调试,所以我讲了对你也没帮助。
A:
L=N\R
B:
fun=fun(L,R)
C:
fun=fun & N mod R
还有个问题,就是这道题有语法错误,当然也可能是你提问时写急了,1个是"Option Explicit"语句和“Private Sub Com1_Click()”不能写在同一行的;2是结束语句有问题,exit语句是强行结束当前过程,而end是子过程结尾的标记,“end sub”的意思是当前子过程的代码到此为止,下边的就不是当前子过程的代码了,而“exit sub”是退出当前子过程,下边一直到"end sub"之间的语句就不执行啦。
当然,这道题如果不是2重的递归,才递归了3次,你应该按步骤计算出来,而且3次递归,如果你的数学很好的话,计算起来很快的,3到5分钟应该解决掉。但是,如果你遇到很麻烦的递归,或者你认为5分钟内计算不出来的填空、选择,你应该抓住核心计算语句,大胆猜测也是一种做题技巧。
大神,太牛了
不客气,不过猜答案只是为了防止答题时间不够,当你做完所有的题后,应该按照最原始的方法进行验证,而且计算时不能只计算每次递归函数的返回值,要像我给你截图那样,什么时候开始第几次递归、什么时候结束、每次递归时所有相关变量的值。的确,3次递归,每次递归加返回值共5个变量,得计算15次,对于一个填空题来说,计算量有点大,但如果你做完了所有的题,可以验证的一定要验证,不能验证的,你应该试着证明递推公式就是“a(n-1)=a(n)\a(0)”,或者像我上边讲的,用“简单的”验证”复杂的“,我上边的举例是用2次递归验证3次递归,如果你遇到10几次的递归,那我们也可以用两三次的递归去验证这10几次递归的结果是否正确。不过这个递推公式是从后往前递推的,有点奇怪,原因你应该看我的截图,先结束的是最后一次调用,这就是我上边说的“先入后出”,所以这个递推公式,它是从最后一个值倒着递推的。
但其他的题结果到底是2,8,135还是135,8,2?不同的题,结论是不一样的。(其实,关键要看你怎么理解“先入后出”,如果你理解不到位,最好别猜。比如,这道题只要把输出写到fun(L, R)前面,输出结果就不应该是倒着的啦,因为输出在递归之前,它应该是正着输出的。)所以猜题也需要验证的,如果时间够用,我们必须做出来答案就是这个,或者证明出答案肯定是这个,而不是猜出来答案可能是这个。