1. (C组T1 3')猜年龄
美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学。他曾在1935~1936年应邀来中国清华大学讲学。 一次,他参加某个重要会议,年轻的脸孔引人注目。于是有人询问他的年龄,他回答说: “我年龄的立方是个4位数。我年龄的4次方是个6位数。这10个数字正好包含了从0到9这10个数字,每个都恰好出现1次。” 请你推算一下,他当时到底有多年轻。 通过浏览器,直接提交他那时的年龄数字。 注意:不要提交解答过程,或其它的说明文字。
【分析】循环+枚举
源代码:
#include <stdio.h>#include <math.h>int main(){ int age; int pow3,pow4; for(age=10;age<=30;age++) { pow3=pow(age,3); pow4=pow(age,4); PRintf("age=%d pow3=%d pow4=%d/n",age,pow3,pow4); } return 0;}程序截图:
【答案】18
※2. (C组T3 8’)振兴中华
小明参加了学校的趣味运动会,其中的一个项目是:跳格子。 地上画着一些格子,每个格子里写一个字,如下所示:(也可参见p1.jpg)从我做起振我做起振兴做起振兴中起振兴中华 比赛时,先站在左上角的写着“从”字的格子里,可以横向或纵向跳到相邻的格子里,但不能跳到对角的格子或其它位置。一直要跳到“华”字结束。 要求跳过的路线刚好构成“从我做起振兴中华”这句话。 请你帮助小明算一算他一共有多少种可能的跳跃路线呢?答案是一个整数,请通过浏览器直接提交该数字。注意:不要提交解答过程,或其它辅助说明类的内容。
【分析】
法一:笔算、数路线
法二:二维数组+递归的综合应用(思想很重要!)
首先把“从我做起,振兴中华”这八个字按照0~7的顺序编好,然后把这个方格存放在一个4*5的二维数组array里面,同时,设定一个同样大小的flag数组来存放行走轨迹,最后还要设定一个road_flag[7]的数组来记录行走的步子是横向还是纵向。 接下来就是利用递归遍历这个二维数组, 递归过程是:从0,0开始,横着或者竖着前进,向前前进一格的条件就是没有超出范围,并且下一格的数字比这一格大1。每次前进一格后,就把flag数组中相应的位置标记为1,同时根据行走的步子的方向来对road_flag中的相应步数进行标记。(这里只需考虑向右走和向下走两种情况) 如果到达了华这个字(相应的数字为7),那么就到了递归出口,判断这一条路径是否符合要求,是否能够输出,然后返回。 函数返回之后,要把相应的路径标记和步子标记清除。 就这样一直遍历,直到把所有的路径都找出来!
参考源代码:
#include <stdio.h>#include <string.h>#define ROW 4#define COL 5int count; //统计路径的次数int flag[ROW][COL]; //路径标记int road_flag[ROW+COL-1]; //步子标记 1-向右走,2-向下走 int road_count; //记录方案总数(走的步数) int road(int arr[][COL],int row,int col){ flag[row][col]=1; //标记路径--每次前进一格后,就把flag数组中相应的位置标记为1 if(arr[row][col]==7) //到达"华"这个字的位置 { count++; printf("No.%d:/n",count); //判断这一条路径是否符合我们的要求 //if(1==road_flag[0] && 2==road_flag[1] && 2==road_flag[2] && 2==road_flag[3] && 1==road_flag[4] && 1==road_flag[5] && 1==road_flag[6]) //{ for(int rloop=0;rloop<ROW;rloop++) { for(int cloop=0;cloop<COL;cloop++) if(1 == flag[rloop][cloop]) //被标记的点,说明该点在行走路线上 printf(" # "); else printf(" ^ "); printf("/n"); } //} return 0; } //横向走 if(col+1<COL && arr[row][col+1]==arr[row][col]+1) //列号+1不超边界,且下一位置对应的数=上一位置对应的数+1 { road_flag[road_count] = 1; //说明可以横向走,并用1标记原来所在的位置 road_count++; road(arr,row,col+1); //递归进行上述过程 //取消路径和步子标记(此过程也是递归进行的) flag[row][col+1] = 0; road_count--; road_flag[road_count] = 0; } //纵向走 if(row+1<ROW && arr[row+1][col]==arr[row][col]+1) //行号+1不超边界,且下一位置对应的数=上一位置对应的数+1 { road_flag[road_count] = 2; //说明可以横向走,并用2标记原来所在的位置 road_count++; road(arr,row+1,col); //递归进行上述过程 //取消路径和步子标记(此过程也是递归进行的) flag[row+1][col] = 0; road_count--; road_flag[road_count] = 0; }}int main() //"从我做起振兴中华"8个字依次对应数字0~7 { int array[ROW][COL]={ {0,1,2,3,4}, {1,2,3,4,5}, {2,3,4,5,6}, {3,4,5,6,7} }; road(array,0,0); //从起点开始,递归遍历 printf("count = %d/n",count); return 0;}程序截图:
【答案】35
※3. (C组T4 13’)幻方填空
幻方是把一些数字填写在方阵中,使得行、列、两条对角线的数字之和都相等。 欧洲最著名的幻方是德国数学家、画家迪勒创作的版画《忧郁》中给出的一个4阶幻方。 他把1,2,3,...16 这16个数字填写在4 x 4的方格中。 如图p1.jpg所示,即:16 ? ? 13? ? 11 ?9 ? ? *? 15 ? 1 表中有些数字已经显露出来,还有些用?和*代替。 请你计算出? 和 * 所代表的数字。并把 * 所代表的数字作为本题答案提交。答案是一个整数,请通过浏览器直接提交该数字。注意:不要提交解答过程,或其它辅助说明类的内容。
【分析】
对比题型:打印n阶魔方阵(n为奇数)
4. (C组T5 5’)公约数公倍数
我们经常会用到求两个整数的最大公约数和最小公倍数的功能。 下面的程序给出了一种算法。 函数 myfunc 接受两个正整数a,b 经过运算后打印出 它们的最大公约数和最小公倍数。 此时,调用 myfunc(15,20) 将会输出:560 // 交换数值void swap(int *a,int *b){ int temp; temp=*a; *a=*b; *b=temp;}void myfunc(int a, int b){ int m,n,r; if(a<b) swap(&a,&b); m=a;n=b;r=a%b; while(r!=0) { a=b;b=r; r=a%b; } printf("%d/n",b); // 最大公约数 printf("%d/n", ____________________________________); // 最小公倍数 }
请分析代码逻辑,并推测划线处的代码,通过网页提交。注意:仅把缺少的代码作为答案,千万不要填写多余的代码、符号或说明文字!!
【分析】辗转相除法
填空后代码:
#include <stdio.h>// 交换数值void swap(int *a,int *b){ int temp; temp=*a; *a=*b; *b=temp;}void myfunc(int a, int b){ int m,n,r; if(a<b) swap(&a,&b); m=a; n=b; r=a%b; while(r!=0) { a=b; b=r; r=a%b; } printf("%d/n",b); // 最大公约数 printf("%d/n", m*n/b); // 最小公倍数 填空位置 }int main(){ int a,b; while(scanf("%d %d",&a,&b)!=EOF) myfunc(a,b); return 0;}程序截图:
【答案】m*n/b
5. (A组T2 6’)排它平方数 小明正看着 203879 这个数字发呆。 原来,203879 * 203879 = 41566646641 这有什么神奇呢?仔细观察,203879 是个6位数,并且它的每个数位上的数字都是不同的,并且它平方后的所有数位上都不出现组成它自身的数字。 具有这样特点的6位数还有一个,请你找出它! 再归纳一下筛选要求: 1. 6位正整数 2. 每个数位上的数字不同 3. 其平方数的每个数位不含原数字的任何组成数位答案是一个6位的正整数。请通过浏览器提交答案。注意:只提交另一6位数,题中已经给出的这个不要提交。注意:不要书写其它的内容(比如:说明性的文字)。
【分析】循环+数位分离+重复判断。特别注意平方数的数据类型要设置为long long int型避免溢出问题。
源代码:
#include <stdio.h>long long int Judge(long long int a[],long long int n) //判断数a的各位数是否有重复 { long long int i,j; long long int flag=1; for(i=0;i<n;i++) { for(j=i+1;j<n;j++) { if(a[i]==a[j]) { flag=0; break; } } } return flag;}long long int Judge(long long int a[],int m,long long int b[],int n) //判断数a与数b的各位数是否有重复 { long long int i,j; long long int flag=1; for(i=0;i<m;i++) { for(j=0;j<n;j++) { if(a[i]==b[j]) { flag=0; break; } } } return flag;}int main(){ long long int i,j,k; long long int num1[20],num2[20]; long long int t,tt,pownum; for(i=100000;i<999999;i++) { pownum=i*i; t=i,tt=pownum; j=0; while(t) { num1[j++]=t%10; t/=10; } if(Judge(num1,j)) { k=0; while(tt) { num2[k++]=tt%10; tt/=10; } if(Judge(num1,j,num2,k)) printf("%lld*%lld=%lld/n",i,i,pownum); } } return 0;} 程序截图:
【答案】639172
6. (A组T4 13')颠倒的价牌
小李的店里专卖其它店中下架的样品电视机,可称为:样品电视专卖店。 其标价都是4位数字(即千元不等)。 小李为了标价清晰、方便,使用了预制的类似数码管的标价签,只要用颜色笔涂数字就可以了(参见p1.jpg)。 这种价牌有个特点,对一些数字,倒过来看也是合理的数字。如:1 2 5 6 8 9 0 都可以。这样一来,如果牌子挂倒了,有可能完全变成了另一个价格,比如:1958 倒着挂就是:8561,差了几千元啊!! 当然,多数情况不能倒读,比如,1110 就不能倒过来,因为0不能作为开始数字。 有一天,悲剧终于发生了。某个店员不小心把店里的某两个价格牌给挂倒了。并且这两个价格牌的电视机都卖出去了! 庆幸的是价格出入不大,其中一个价牌赔了2百多,另一个价牌却赚了8百多,综合起来,反而多赚了558元。 请根据这些信息计算:赔钱的那个价牌正确的价格应该是多少?答案是一个4位的整数,请通过浏览器直接提交该数字。注意:不要提交解答过程,或其它辅助说明类的内容。
【分析】
源代码:
#include <stdio.h>int main(){ int i,j,p1,p2,t; int p,a[4]; int reversep1,reversep2; //int a[7]={1,2,5,6,8,9,0}; //int reverse[7]={1,2,5,9,8,6,0}; for(p1=1000;p1<=9999;p1++) { i=0; t=p1; while(t) { a[i++]=t%10; t/=10; } for(p=0;p<4;p++) { if(a[p]==6) a[p]=9; else if(a[p]==9) a[p]=6; } reversep1=1000*a[0]+100*a[1]+10*a[2]+a[3]; for(p2=1000;p2<=9999;p2++) { j=0; t=p2; while(t) { a[j++]=t%10; t/=10; } for(p=0;p<4;p++) { if(a[p]==6) a[p]=9; else if(a[p]==9) a[p]=6; } reversep2=1000*a[0]+100*a[1]+10*a[2]+a[3]; // printf("%d %d %d %d/n",p1,reversep1,p2,reversep2); if((reversep1-p1>-300 && reversep1-p1<-200) && (reversep2-p2>800 && reversep2-p2<900) && (reversep1+reversep2-p1-p2==558)) printf("%d %d %d %d/n",p1,reversep1,p2,reversep2); } } return 0;} 程序截图:
【答案】9088
7. (A组T6 10')逆波兰表达式 正常的表达式称为中缀表达式,运算符在中间,主要是给人阅读的,机器求解并不方便。 例如:3 + 5 * (2 + 6) - 1 而且,常常需要用括号来改变运算次序。 相反,如果使用逆波兰表达式(前缀表达式)表示,上面的算式则表示为: - + 3 * 5 + 2 6 1 不再需要括号,机器可以用递归的方法很方便地求解。 为了简便,我们假设: 1. 只有 + - * 三种运算符 2. 每个运算数都是一个小于10的非负整数 下面的程序对一个逆波兰表示串进行求值。 其返回值为一个结构:其中第一元素表示求值结果,第二个元素表示它已解析的字符数。struct EV{int result; //计算结果 int n; //消耗掉的字符数 };struct EV evaluate(char* x){struct EV ev = {0,0};struct EV v1;struct EV v2;if(*x==0) return ev;if(x[0]>='0' && x[0]<='9'){ev.result = x[0]-'0';ev.n = 1;return ev;}v1 = evaluate(x+1);v2 = _____________________________; //填空位置if(x[0]=='+') ev.result = v1.result + v2.result;if(x[0]=='*') ev.result = v1.result * v2.result;if(x[0]=='-') ev.result = v1.result - v2.result;ev.n = 1+v1.n+v2.n;return ev;}请分析代码逻辑,并推测划线处的代码,通过网页提交。注意:仅把缺少的代码作为答案,千万不要填写多余的代码、符号或说明文字!!
【分析】前中后缀表达式的求值(结合数据结构栈的内容)
填空后代码:
#include <stdio.h>#define maxlen 105struct EV{ int result; //计算结果 int n; //消耗掉的字符数 };struct EV evaluate(char* x){ struct EV ev = {0,0}; struct EV v1; struct EV v2; if(*x==0) return ev; if(x[0]>='0' && x[0]<='9') { ev.result = x[0]-'0'; ev.n = 1; return ev; } v1 = evaluate(x+1); v2 = evaluate(x+v1.n+1); //填空位置 if(x[0]=='+') ev.result = v1.result + v2.result; if(x[0]=='*') ev.result = v1.result * v2.result; if(x[0]=='-') ev.result = v1.result - v2.result; ev.n = 1+v1.n+v2.n; return ev;}int main(){ EV v=evaluate("-+3*5+261"); printf("%d/n",v.result); return 0;}程序截图:
【答案】42
新闻热点
疑难解答
图片精选