阅读程序,写运行结果(25分左右,3-4题)
其实很容易,目的几乎是送分,而且占的分数很多,但得分率却不见得高。很容易不明不白的就把分(全)丢了!!!
这部分程序考3个方面:
1. 程序设计语言本身,如循环、递归、值型参和变量型参数、跟踪变量等;
2. 归纳和数学运算能力;
3. 是否掌握了一些常用算法(程序段)的框架;
4. 细心、耐心等心理品质;灵感+编程的量等;
一般做这类题目的核心是找程序目的:
即这个程序想干什么。迄今为止考过的题目还没有“乱写”的,总有一点“写作目的”的。抓住了它,不仅得出答案变得很容易了,而且对自己的结果也会比较有信心。
一般的解题步骤如下:
1. 从总体上通读程序,大致把握程序的目的和算法;
2. 猜测变量的作用,跟踪主要变量值的变化(列表),找出规律;
3. 将程序分段,理清每一小段的作用和目的(灵感+关键表达式和语句的领会);
4. 看清输入、按照输出格式,写出结果;
5. 带着得到的结果回到程序进行检查;
下面举几个例子。

?        1.基本题(考语言本身,尤其是循环嵌套。1999年初中组)
Program excpl;
var
x,y,y1,jk,j1,g,e:Integer;
a:array[1..20] of 0..9;
begin
x:=3465; y:=264; jk:=20;
for j1:=1 to 20 do a[j1]:=0;
while y<>0 do
    begin
      y1:=y mod 10;
      y:=y div 10;
      while y1<>0 do
      begin
        g:=x;
        for e:=Jk downto 1 do
          begin
            g:=g+a[e];
            a[e]:=g mod 10;
            g:=g div 10
          end;
        y1:=y1-1
      end;
      jk:=jk-1
    end;
j1:=1;
while a[j1]=0 do j1:=j1+1;
for Jk:=j1 to 20 do write(a[jk]:4);
writeln
end.
程序运行结果为:___________________________。

解答:
程序不长,但是有一定的难度。高手最多半分钟就看懂了程序的意思,但初学者往往算了很久得出了结果却是错的。下面我们还是先以一个初学者的身份分析一下这个程序。记住,不要一开始就模拟电脑来一个个语句“执行”-------你算过自己是多少Hz的CPU没有?!
首先是看看变量的名字,可惜分区联赛题目中的变量不是i就是j,很讨厌。i和j一般作为循环计数器,没有什么意思,因此不要管它了。然后要看变量在程序的哪里出现过,着重看它与其它变量的相互引用关系,猜测它的作用。例如上题:x只在g:=x中出现,暂时不要管它,因为它很可能只是一个初始数据。y有三处:1) while y<>0 do
2) y1:=y mod 10;
3) y:=y div 10;
很明显,y每次少了最后一位数字,把这位数字给了y1。有经验的选手应该体会到了什么,不过我们继续。
现在我们知道了:y对程序的作用是:每次提供最后一位给y1,即y1每次的值依次是:4,6,2
那么再看y1,它出现在两个地方:
1)while y1<>0 do
2)y1=y1-1
很明显就是一个循环次数嘛!循环y1次!
再看jk:
1)for e:=jk downto 1 do
2)jk:=jk-1
jk作为循环初始值,居然一次比一次少...其原因有待进一步分析。
再看j1:
1)for j1:=1 to 20 do a[j1]:=0;
2)j1:=1;
3)while a[j1]=0 do j1:=j1+1;
4)for Jk:=j1 to 20 do write(a[jk]:4);
显然,j1和其它变量没有什么联系。1)是初始化,2)3)4)是输出数组a。
再看g: 出现的位置是几层循环之内了,应该很重要!一会儿再分析!
再看e: 作为循环变量,没有什么意思。
通过变量分析,我们知道了:x,y是数据,y每次提供最后一位给y1,循环y1次。j1和g的作用有待分析。

下面根据程序结构,把程序分成几块,逐个研究。最主要的程序段是两个WHILE循环中套一个FOR循环,三重循环!!!其实,最外面一层很明确:判断什么时候结束(y=0)。前后都很简单,是一些变量和数组的初始化、输入、输出等,下面重点剖析核心程序段。
1) x:=3465; y:=264; jk:=20;
     for j1:=1 to 20 do a[j1]:=0;
    输入与变量、数组的初始化,不要管它。

2)while y<>0 do
begin
    y1:=y mod 10;
    y:=y div 10;
    while y1<>0 do
    begin
<< g:=x;
      for e:=Jk downto 1 do
      begin
        g:=g+a[e];
        a[e]:=g mod 10;
        g:=g div 10
      end;
   >>
      y1:=y1-1
    end;
jk:=jk-1
end;

3)
j1:=1;
while a[j1]=0 do j1:=j1+1;
for Jk:=j1 to 20 do write(a[jk]:4);
writeln
从前往后,找到<>0的位置开始,输出数组元素的值(输出结果),也不要管它。

块2最重要。
它的思想是:每次取Y的最第位y1,执行<<运算>>y1次,每次把jk减1。
现在最重要的是<<运算>>中的在干什么?
注意到最后输出的a[],要留意a[]的变化!
a[e]总是取个位(g mod 10),g每次少一位,和a[e-1](别忘了e在循环!)相加...
难道是...高精度加法???RIGHT!
它执行了y1次,y1每次都是y的个位!对了。程序就是在做x*y
所以答案就是 3465*264=914760
再看它的输出格式,输出的应该是:___9___1___4___7___6___0

其实有经验的话,看到g这个变量名和g:=g+a[e]; a[e]:=g mod 10;这几个标志句子。就可以一下子知道程序的用意了。
总结一下本题:重点考循环嵌套的执行过程以及对除法运算中的商、余数的基本方法;主要程序段可以通过列表了解变量的变化情况;要细心、耐心;题目的本身没有多少值得研究的价值!!!但有些题目纯粹考算法思路,如下面的例子:

?        2. 算法题
program ex2;
var i,j,n:longint;
    b:array [0..31] of 0..1;
begin
     n=1999;
     i:=0;
     while n<>0 do
     begin
          b[i]:=n mod 2;
          i:=i+1;
          n:=n div 2
     end;
     for j:=i-1 downto 0 do write(b[j]);
end.
输出什么?
解答:很明显,是把十进制整数转换成二进制数,所以输出11111001111

?        3.有些题目则是考数学,或根据一些基本规则重复地做某个操作。如:
program exp1 (imput,output);
var i,,s,max: integer;
    a:array [1..10] of integer;
begin
   for i:=1 to 10 do   read (a[i]);
   max:=a[1] ;s:=a[1];
   for i:=2 to 10 do
     begin
       if s<0 then s:=0;
       s:= s+a[i];
if s>max then max:=s
end;
writeln(‘max=’, max)
end.
输入:8 9 -1 24 6 5 11 15 -28 9
输出:max=
解答:本题主要做累加:s:= s+a[i];再根据结果打擂台。
但最关键的语句是:if s<0 then s:=0;它的作用是把s<0的前若干个元素的和值屏蔽掉(置0)。了解了这一点,题目就很简单了。步骤如下:
s<0?            s=8          s>max?           max=8;
I=2              N             8+9=17          Y              max=17;
I=3              N             17-1=16         N              max=17;
I=4              N             16+24=40        Y              max=40;
I=5              N             10+6=46         Y              max=46;
I=6              N             46+5=51         Y              max=51;
I=7              N             51+11=62        Y              max=62;
I=8              N             62+15=77        Y              max=77;
I=9              N             77-28=49        N              max=77;
I=10             N             49+9=58         N              max=77;
所以结果为:77。
    小结:本质是求一个n长的整数数列的连续x长的子序列,要求子序列的和最大!
          注意:s和max!!!另外本题给的输入数据比较简单,所以有很多人没有完全懂也算对了结果,把数据改成如下:-1 12 -103 65 34 -4 -27 8 -1234 9,问结果是多少呢?答:9!!!

?        4.考子程序的调用,尤其是递归或带参数(值参与变量型参数),如:
PROGRAM EX3;
CONST N=10;
VAR S,I : INTEGER;
FUNCTION CO(I1:INTEGER) : INTEGER;
VAR J1,S1 : INTEGER;
BEGIN
S1:=N;
FOR J1:= (N-1) DOWNTO (N-I1+1) DO
S1:= S1*J1 DIV (N-J1+1);
CO:=S1
END;
BEGIN
S:=N+1;
FOR I:= 2 TO N DO S:=S + CO(I);
WRITELN(‘S=’,S);
END.
解答过程:
(1)       如果有子程序,一般先读主程序,了解主程序什么时候调用子程序?干什么的?调用了多少次?本题调用了n-1次,并且累加函数的返回值!
(2)       再单独阅读子程序,分析变量、参数和返回值,确定它的功能。本题函数猛一看好象比较复杂,不过是通过一个循环结构完成累乘和累除,下面再具体分析!
(3)       通过列表,观察子程序中的变量变化情况,以便找出规律,确定子程序的作用。本题如下:
CO(2)=10*9/2
CO(3)=10*9*8/2/3
CO(4)=10*9*8*7/2/3/4
……
发现,好象是组合数学的公式:CO(i)=10!/(i!*(10-i)!)
即:C(m,n)=m!/(n!*(m-n)!)=m*(m-1)*……*(m-n+1)/n!
(4)       所以结果很明确:C(10,0)+ C(10,1)+……+C(10,9)+ C(10,10)=722
    总结:灵感来源于丰富的数学基础和经验!

posted on 2011-08-05 10:37  shallyzhang  阅读(204)  评论(0)    收藏  举报