首页 > 编程 > C++ > 正文

2013年第四届蓝桥杯C/C++组真题补充训练(一,2017.3.4)未完待续

2019-11-06 07:43:27
字体:
来源:转载
供稿:网友

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


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选