资料名称: C语言程序设计二级题库院系班级:软件学院1302软件工程姓名:阳兴
学号:139894
目录
第一部分:应试攻略 (2)
一、灵活运用多种求解方法 (2)
二、熟悉基本问题的求解思路 (2)
三、熟记典型问题的答案 (3)
四、程序题考试操作要点 (4)
第二部分:程序改错题典型范例 (6)
第三部分:程序填空题典型范例 (8)
第四部分:程序设计题典型范例 (11)
第五部分:程序题主要考点 (14)
【考点一】在一定范围内求满足条件的整数个数(或求最大最小值、求和)。 (14)
【考点二】方程或不等式求整数解问题。 (21)
【考点三】数列求项或求和问题 (28)
第六部分:知识点归纳 (31)
一、数据处理 (31)
二、基本语句 (32)
第一部分:应试攻略
一、灵活运用多种求解方法
由于湖南省二级考试所有程序题(包括:改错题、填空题和编程题)采取计算机自动评分,而评分的标准就是你最后填写的程序的运行结果而不是代码!因此,在不得已的情况下(有时也是更直接甚至是更简洁的办法),可利用以下方法之一解决问题!
1、按自己的思路编程。对于改错题或填空题,如果看不懂原代码,以至无法求解,可
以按照自己的思路重写代码求解。
2、通过“Turbo C for Windows实验开发环境”之“典型源程序”获得求解方法甚至是
源代码。也可通过“库函数查询”获得相关函数的帮助信息。如图1所示。
3、借助Windows附件中的计算器解决问题(如数制转换、开方、乘方、求和等)。
4、数学方法求解。
图1:通过开发环境获得程序信息
5、利用EXCEL求解。(示例中将重点介绍这种方法)
二、熟悉基本问题的求解思路
1、求整数的各位数字
主要利用除法运算和求余运算。基本思路是:先将要求的数字移到个位,再取出个位。例如,x为四位数,则:
x/1000:是千位数字。(整型数据相除得到的商是整数)
x/100%10:百位数字。
x/10%10:十位数字。
x%10:个位数字。
2、判断一个整数是否为素数
判断整数N>2是否为素数的主要方法是:
----若[3,sqrt(N)]上无N的因子,则N为素数。
----将区间改为为[3,N/2]或[3,N-1],上述结论仍然成立。
----将“因子”改为“质因子”或“奇数因子”,上述结论仍然成立。
要注意,1既不是素数,也不是合数。在考试中,为了简便,建议将区间定为[3,N-1]。参考代码如下:
/*判断n是否为素数:返回1表示是,0表示否*/
int isPrime(long n)/*判断奇数是否为质数*/
{ long k;
for(k=3;k if(n%k==0)break; return (k>=n); } 3、判断一个整数是否为完全平方数 设K、N均为long类型的变量,其中N已赋值为一个正整数,取K=sqrt(N)。则N为完全平方数<=>K*K与N相等。 注意:使用sqrt函数时,一定要在main函数前添加预处理命令:#include "math.h" 4、确定整数位数 基本方法是删除个位法:while(n)k++,n/=10; 这种方法也可用于解决: (1)整数逆序输出:while(n){printf("%d",n%10);n/=10;} (2)十进制整数化为R进制整数: whille(n) { y+=t*(n%r); /*y初值为0,t初值为1;1 t*=10;n/=r; }/*y即为R进制整数(十进制表示形式)*/ 有时可用更简洁的方法确定整数位数。如x是不超过五位数的整数,其位数为: (x>9999)+(x>999)+(x>99)+(x>9)+1。 三、熟记典型问题的答案 1、完数:一个正整数N的约数和是N的倍数,则称N为完数。10000内的完数只有七个:1、6、28、120、496、67 2、8128。如果考题将完数定义为“真因子之和等于本身的数”,则完数不包括1、120、672。 2、水仙花数:一个三位正整数N的各位数字的立方和等于N,则称N为水仙花数。水仙花数共四个:51 3、370、371、407 3、完全平方数:即平方根为整数的正整数。显然为:12、22、32、…… 4、质数:又名素数,指恰有两个约数的正整数。100以内的质数共25个:2、3、 5、7、11、 13、17、19、23、29、31、37、41、43、47、53、59、61、67、71、73、79、83、89、97 5、同构数:如果N是N2的尾数,则称N是同构数。[1,10000]上的同构数有八个:1,5,6,25,76,376,625,9376。为了方便记忆,可分成二组:(1,5,25,625)、(6,76,376,9376)。 四、程序题考试操作要点 1、程序改错题操作要点示例 (1)打开VC或Turbo C for Windows开发环境,必要时创建文件; (2)复制代码。在考试系统中单击“复制代码”按钮; (3)将代码粘贴到开发环境中; (4)审清题意,改正程序中的错误后,运行程序; (5)将程序运行时的显示结果填写到考试系统“程序改错题”的“结果”输入框中,如图2所示。再单击“保存”按钮即可。 图2:程序改错题窗口 图2:程序改错题操作界面 一般而言,程序改错题不一定把每一条语句都看懂。关键是审清题意,直接分析出现错误的语句的作用,从而纠正错误。 2、程序填空题操作要点示例 (1)打开VC或Turbo C for Windows开发环境,必要时新建文件; (2)复制代码。在考试系统中单击“复制代码”按钮; (3)将代码粘贴到开发环境中; (4)审清题意,填空后,运行程序; 一般而言,程序填空题不一定把每一条语句都看懂。关键是审清题意,记全、记准已知条件和需要解决的问题,直接分析填空处的语句作用,从而完成填空。 (5)将程序运行时的显示结果填写到考试系统“程序填空题”的“结果”输入框中,如图3所示。再单击“保存”按钮即可。 图3:程序填空题操作界面 对于程序设计题,直接在开发环境中完成程序的设计和调试,并将程序运行的结果填写在“结果”输入框中,再单击“保存”按钮即可。当然,这一结果是你编程后得到的,还是你用数学方法或EXCEL得到的,计算机评分时不管这些,只要结果正确! 第二部分:程序改错题典型范例 1、下面给出的函数fun(n,r)用于返回二进制正整数n的r进制数(1 long fun(long n,int r) { long y=0,t=1; while(n) { y+=t*(n%r); t*=10; n%=r; /*本行语句有错误*/ } return t; /*本行语句有错误*/ } main() { long a=197;int r=7; printf("%ld",fun(a,r)); } 参考答案: n%=r; 改为n/=r; return t; 改为return y; 输出结果:401 解题技巧: A.十进制整数化为r进制整数的基本方法是除r取余法。按照这种思路去阅读代码,很容易认清各语句的作用,从而纠正错误。 B.根据题目叙述,结合main函数的代码,程序就是输出197的7进制整数。直接利用除7取余法即可用笔算得到结果。或者,利用Windows的计算器得到结果。 EXCEL解法 (1)在A1单元格输入十进制整数, 在B1单元格输入R的值。如图4所 示。 (2)在A2输入公式: =INT(A1/$B$1) (3)在B2输入公式: =MOD(A1, $B$1) (4)选择A2至B2,向下拖填充柄, 至A列出现0为此。此时,由B列由 下向上至B2,即为A1单元格整数化 为R进制数。 2、相差为2的两个素数称为双胞胎 图4:EXCEL求解图示 数。下列程序用于求[200,1000]上有多少对双胞胎数。改正程序中的错误后调试程序,并指出程序运行的结果。 int isZ(int x) { int k=2; while(k*k<=x) if(x%k==0)continue;else k++; /*本行语句有错误*/ return (x>1)&&(k*k>x); } main() { int x,n=0; for(x=203;x<997;x+=2) if(isZ(x)||isZ(x+2))n++; /*本行语句有错误*/ printf("%d",n); } 参考答案: if(x%k==0)continue;else k++;改为if(x%k==0)break;else k++; if(isZ(x)||isZ(x+2))n++;改为if(isZ(x)&&isZ(x+2))n++; 输出结果:20 特别提示:return (x>1)&&(k*k>x); 不能修改为return k*k>x;否则1会认为是素数。而1既不是素数,也不是合数。 解题技巧: 根据题意,很容易分析出主函数中的if语句是用于判断x和x+2是否为素数的。因此推断出,isZ函数的作用是判断素数。而判断一个整数x是否为素数的基本方法就是在[2,sqrt(x)]上搜索x的约数。按照这一思路分析代码,即可纠正错误。 3、下列程序用于计算四位数的奇数中,各位数字之积是60的正整数倍的数的和。改正程序中的错误后调试程序,并指出程序运行的结果。 main() { int k,t,s=0; /*本行语句有错误*/ for(k=1001;k<10000;k+=2) { t=(k/1000)*(k/100%10)*(k/10%10)*(k%10); if(t%60==0)s+=t; /*本行语句有错误*/ } printf("%ld",s); } 参考答案: int k,t,s=0; 改为int k,t;long s=0; if(t%60==0)s+=t; 改为if(t&&t%60==0)s+=k; 输出结果:3456254 解题技巧: A.定义变量的语句出现错误,无非两种可能: 变量初值错误或未赋初值。一般而言,用于计数、求和的变量初值为0。但要注意程序的处理方法,计数变量的初值也可能是1、求和变量的初值也可能是满足条件 的第一个数据。 变量类型错误。这主要是由于数据超过了变量的赋值范围。建议对整数类计数或求和问题,将变量类型均定义为long类型。本题中,从printf("%ld",s)也可看出变量 s为long类型。 B.本题中的第二个错误很容易忽视:审题不清。题目要求的是60的正整数倍,因此,还必须有条件t>0。 4、下列程序用于计算满足条件的四位数ABCD的个数:是8的倍数;A+B=B+C。改正程序中的错误后调试程序,并指出程序运行的结果。 main() { int k,n; /*本行语句有错误*/ for(k=1000;k<10000;k++) /*本行语句有错误*/ if(k/1000==k/10%10)n++; printf("%d",n); } 参考答案: int k,n; 改为int k,n=0; for(k=1000;k<10000;k++)改为for(k=1000;k<10000;k+=8) 输出结果:110 解题技巧: A.正如上题分析,变量定义的语句出错,只有两个可能。 B.根据题意,搜索的整数必须满足三个条件:其一,是四位正整数;其二,是8的倍数;其三,A=C。以此为线索,易知,第二个条件未在代码中体现。考虑到1000是8的倍数,因此,循环变量的增量(也叫步长)修改为8即可。 第三部分:程序填空题典型范例 1、下列程序可输出1000~9999之间所有四位数的个数:它是一个完全平方数,其左两位数字之和为10,右两位数字之积为18。请在下划线上填写适当的语句后运行程序,并给出程序运行的结果。 main() {int k,x,n=0; for(k=32;k<100;k++) { x=___________; if(x/1000+(x/100%10)==10) if(__________________)n++; } printf("%d",n); } 参考答案:k*k (x/10%10)*(x%10)==18 程序运行结果:1 解题技巧: A.根据题意(读懂、认准题目的已知条件、需要得到什么结果?这是理解代码的关键!),四位数必须是一个完全平方数,但代码中并未对四位数进行循环搜索,而是由k在区间[32,100)上穷举。其意图是什么呢?由于312=961是三位数,而322=1024是四位数(四位数中最小的完全平方数!),1002是五位数!发现了这一特点,思路便变得清晰:由k*k得到平方数(当然是四位数),可有效避免平方数的判断,简化代码。故第一空应填写:k*k B.if语句是判断平方数x是否满足题设条件。代码已经给出了一个条件x/1000+(x/100%10)==10,也就是千位数字与百位数字(四位数的左两位)之和是否为10。第二个条件自然是右两位数字之积是否为18:(x/10%10)*(x%10)==18。 2、斐波那契数列的前二项均为1,从第三项起,每项均为前两项的和。下列程序求10000000内最大的斐波那契数。请在下划线上填写适当的语句后运行程序,并给出程序运行的结果。main() { long a=1,b=1; while(_______________) b+=a,__________________; printf("%ld",a); } 参考答案:b<=10000000 a=b-a 程序运行结果:9227465 解题技巧: A.题目是求10000000内最大的斐波那契数。而代码中的输出语句是printf("%ld",a);->可见循环条件是b<=10000000。为什么不是a<=10000000?因为如果是这样,则终止循环时,必有a >10000000,不满足题的要求。注意:a是b的前项。 B.从代码来看,其算法的基本思路是:不用第三个变量,直接根据当前项b及前项a计算出下一项及其前项。因此,第二个空应填a=b-a。但是,你想不到怎么办?改代码!用你熟悉的方法,增加第三个变量t=a+b,a=b,b=t! 3、以下程序求最大的三位数:其每位数字互异且立方和等于该数。请在下划线上填写适当的语句后运行程序,并给出程序运行的结果。 main() {int k,a,b,c; for(k=999;k>=100;k--) { a=k/100;___________;c=k%10; if(a!=b&&a!=c&&b!=c) if(a*a*a+b*b*b+c*c*c==k)___________; } printf("%d",k); } 参考答案:break 程序运行结果:407 解题技巧: A.既然是求最大的三位数,当然是从大到小搜索,找到满足条件的即结束。因此,第二个空该填break。 B.条件是各位数字互异且立方和等于数本身。因此,需求出各位数字。代码中已求出百位数字a和个位数字c,故第一个空中应求十位数字b,故应填b=k/10%10。 4、仔细阅读以下程序,根据程序实现的功能,在下划线上填写适当的语句后运行程序,并给出程序运行的结果。 int isrep(long n) /*判断整数各位数字是否有重复*/ { int k;long m; while(n) { k=n%10;m=n/10; /*取n的个位与其他位比较*/ while(m) if(__________)return 1;else m/=10; _____________ } return 0; } main() {long x=3456123; printf("%d",isrep(x)); } 参考答案:k==m%10 n/=10; 程序运行结果:1 解题技巧: 从代码注释可得到算法的基本思路: A.取n的个位数字k:k=n%10;m=n/10; B.取n的其他位组成的数:m=n/10; C.判断k是否在m中出现:(采取删除个位法) a.取m的个位与k比较:如果相等,返回值1,结束。 b.删除m的个位:m/=10。 c.如果m=0,转D,否则转a。 D.删除n的个位:n/=10 E.如果n=0,返回值0,结束。否则转A。 第四部分:程序设计题典型范例 1、编程求解有多少个这样的四位正整数:其各位数字的和是3的倍数含数字5。 main() { int k,m,n=0; for(k=1005;k<9975;k+=3) { m=k; while(m)if(m%10==5)break;else m/=10; if(m)n++; } printf("%d",n); } 参考答案:1059 解题技巧: 如果你无法完成代码,不妨用数学方法解决! 当然,也可利用EXCEL求解: (1)先生成3的倍数:在A1输入1005、A2输入1008,再选择A1和A2,向下拖填充柄至得到9975; (2)再从3的倍数中找出含数字5的数:在B1单元格输入公式:=IF(FIND("5",A1&"5")<5,1,"") 注意:公式=IF(FIND("5",A1),1,"")也可实现查找,但是,由于FIND函数如果未找到串,返回值为#V ALUE!,不方便SUM函数的处理。 (3)选择B1,向下拖填充柄至最后行; (4)在C1输入:=SUM(B:B)。 这时C1显示值为1059,即本题答案。 2、求[2,1000]上所有同构数之和。如果n2的低位是n,则称正整数n为同构数。 分析:设k位数为p,则k是同构数当且仅当k2-k能被10p整除。求解的基本思路是: (1)k=2,s=0。对k进行穷举搜索。和值s初值为0。 (2)根据k的位数p确定t=10p A.t=1,n=k B.while(n)t*=10,n/=10 (3)如果k2-k能被t整除,则s+=k (4)k++。如果k>1000则输出和值s,程序结束。否则转(2) main() {int s=0,t,n;long k; for(k=2;k<=1000;k++) { t=1;n=k; while(n)t*=10,n/=10; if((k*k-k)%t==0)s+=k; } printf("%d",s); } 参考答案:1113 EXCEL 解法 (1)在A 列输入2,3,...,999。如图5所示。 (2)在B2输入公式:=A2*A2-A2 (3)在C2输入公式:=(A2>99)+(A2>9)+1 (4)在D2输入公式:=IF(MOD(B2,10^C2)=0,A2,"") (5)选择B2至D2,向下拖填充柄至最后行; (6)在E2输入公式:=SUM(D:D) 此时E2显示1113,即本题答案。 3、某些分数的分子分母都是二位正整数的真分数,如果将分子的两位数字相加作分子,分母两位数字相加作分母,得到的分数值不变。求这些分数的分子与分母的总和。 分析:设分子为x ,分母为y ,则x if(y*(x/10%10+x%10)==x*(y/10%10+y%10))s+=x+y; printf("%d",s); }/*x/y=m/n 即xn=ym ,转化以避免分数运算带来的误差。*/ 参考答案:10134 EXCEL 解法 图5:EXCEL 求解图 (1)在A 列输入分子10-98、第一行输入分母11-99,如图6所示; (2)在B2单元格输入公式: =IF(AND($A2 AND 包括二个条件: $A2 (INT($A2/10)+MOD($A2,10))*B$1=(INT(B$1/10)+MOD(B$1,10))*$A2),$A2+B$1,""):表示分子的两个数字相加后,与分母两个数字之和的商不变。 (3)选择B2,向右拖填充柄至CL2; (4)选择B2至CL2,向下拖填充柄至第90行; (5)在CM2输入公式:=SUM(B2:CL90) 此时CM2单元格显示10134,即本题答案。 4、正整数A 、B 的最大公约数为10,最小公倍数为100,且A 分析:由题意,可设A=10M ,B=10N ,M 、N 互质。则有: AB=1000(数学结论:两个整数之积等于其最大公约数与最小公倍数之积),即:MN=10。故(M,N)=(1,10)或(2,5)。 以上是数学解法。编程求解则可通过以下思路实现: (1)A=10(A 是10的倍数,从10开始搜索求解) (2)求B :如果1000%A=0则转(3),否则转(6) (3)B=1000/A (利用上面的数学结论)。若A>=B 则结束。 (4)求A 、B 的最大公约数F (5)如果F=10,则得到一组解,解数N++ (6)A+=10(搜索下一个可能的解) (7)如果A>100则结束。否则转(2) 图6:EXCEL 求解图示 main() { int a=10,b,n=0,c,d,r; while(a<=100) { if(1000%a==0) { b=1000/a; if(a>=b)break; c=b;d=a; while(d) r=c%d,c=d,d=r; if(c==10)n++; } a+=10; } printf("%d",n);} 第五部分:程序题主要考点 【考点一】在一定范围内求满足条件的整数个数(或求最大最小值、求和)。 【求解方法】利用循环,在指定范围内搜索求解。 【易错点】 统计整数个数或求和的变量未赋初值。一般应赋初值0。 求和时变量类型错误,造成数据溢出。建议用于整数求和的变量均定义为long类型。 数据过大时,用double类型。 比较两个数是否相等的运算符是"=="而不是"="。 调用数学函数未用预处理命令:#include "math.h" 【程序示例】 1、编写程序,计算0~50范围内有多少个数,其每位数字之积小于每位数字和。 分析:一位数显然不满足条件。求解思路是: (1)k=10,n=0(k作循环变量,n统计满足条件的数据个数) (2)取k的十位数字a和个位数字b:a=k/10,b=k%10 (3)如果ab (4)k++ (5)如果k>50则输出n的值,程序结束。否则转(2) 参考代码(n=17): main() { int k,a,b,n=0; for(k=10;k<=50;k++) { a=k/10,b=k%10; if(a*b } printf("%d",n); } 显然,该题用数学方法也很容易得到结果。 借助EXCEL,求解更简单。如图7,基本操作步骤: 图7:EXCEL求解图示 (1)在A1、A2单元格内分别输入10、20 (2)选择A1、A2两个单元格,向下拖动填充柄,拖到第50行时松开鼠标。这时,A列有数据10-50。(在EXCEL中,输入等差数列的前二项后,选择其单元格,拖其填充柄即可得到等差序列。) (3)在B1单元格输入公式(取十位数字):=int(A1/10) (4)在C1单元格输入公式(取个位数字):=mod(A1,10) (5)在D1单元格输入公式:=if(B1*C1 (6)选择B1、C1和D1单元格,拖动填充柄至第50行。 (7)在E1单元格输入公式:=sum(D1:D50) (8)这时E1单元格显示数值17。这就是问题的答案。 2、一个正整数如果等于其所有因子之和,则称该数为完数。求[6,10000]上完数的个数。分析:从数学概念上讲,如果整数a能被整数k整除,就称k为a因子,又叫约数。本题中,因子是指正整数,且没有包括a本身。 求解思路是: (1) k=6,n=0(k作循环变量,n统计满足条件的数据个数) (2)求k的所有因子之和s: A.s=1,t=2(1是k的因子,作为和s的初值;t用于因子搜索) B.如果k%t为0,则t是k的因子,更新和值:s=s+t C.t++ D.如果t>k/2则转(3),否则转B(k的最大因子不超过k/2) (3)如果s与k相等,则n++ (4)确定下一个整数是否为完数:k++ (5)如果k>10000则输出n,程序结束。否则转(2) 参考代码(n=4): main() { int k, s,i,n=0; for(k=6;k<10000;k++) { s=1; /*1是因子,直接作为和的初值*/ for(i=2;i<=k/2;i++) /*求k的所有因子之和*/ if(k%i==0)s+=i; if(s==k)n++; /* k为完数时累计个数*/ } printf("%d",n); } 3、求100~500间除5余 4、除7余2的数的和。 main()/*参考答案:3678 */ { int k,s=0; for(k=100;k<500;k++) if(k%5==4&&k%7==2)s+=k; printf("%d",s); } 数学解法: 设被5除余4的数为5N+4,该数除7余2,只需5N除7余5,即N除7余1。故N=7k+1。所以满足题设条件的数可表示为5(7k+1)+4=35k+9。 再由100<=9+35k<=500得到3<= k<=14。从而所求和为: (9+35*3)+(9+35*4)+...+(9+35*14) =9*12+35*(3+14)*12/2=3678