第五届蓝桥杯大赛个人赛(软件类)省赛真题-参考答案全(Java A组)

第五届蓝桥杯大赛个人赛(软件类)省赛真题-Java本科A

个人整理编写,非官方答案,有错误的地方也请指出。

编程方法供参考,转载请注明出处。


第一题:
标题:猜年龄
    小明带两个妹妹参加元宵灯会。别人问她们多大了,她们调皮地说:“我们俩的年龄之积是年龄之和的6倍”。小明又补充说:“她们可不是双胞胎,年龄差肯定也不超过8岁啊。”
    请你写出:小明的较小的妹妹的年龄。
注意: 只写一个人的年龄数字,请通过浏览器提交答案。不要书写任何多余的内容。


这题没敲代码,纸上直接算出来了。。
答:10岁。(分别是10岁和15岁)

第二题:
标题:李白打酒
    话说大诗人李白,一生好饮。幸好他从不开车。
    一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
    无事街上走,提壶去打酒。
    逢店加一倍,遇花喝一斗。
    这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。 
    请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
    注意:通过浏览器提交答案。答案是个整数。不要书写任何多余的内容。

// 李白打酒
public class Main {
	static int N = 0;
	//函数参数分别代表当前酒几斗,遇店次数,遇花次数。
	//题目给定最后一次遇到花,故取10-1=9,函数中定义最后喝剩的应该是1.(即再遇到一次花就喝完了)
	static void Libai(int now, int i, int j) {
		if (now >= 0) {
			if (i == 0 && j == 0 && now == 1) {
				N = N + 1;
				return;
			}
			if (i == 0) {
				Libai(now - 1, i, j - 1);
				return;
			}
			if (j == 0) {
				Libai(now * 2, i - 1, j);
				return;
			}
			Libai(now - 1, i, j - 1);
			Libai(now * 2, i - 1, j);
		}
	}
	public static void main(String[] args) {
		Libai(2, 5, 9);
		System.out.println(N);
	}
}


第三题:

标题:神奇算式

    由4个不同的数字,组成的一个乘法算式,它们的乘积仍然由这4个数字组成。
    比如: 
210 x 6 = 1260 
8 x 473 = 3784
27 x 81 = 2187 
    都符合要求。
    如果满足乘法交换律的算式算作同一种情况,那么,包含上边已列出的3种情况,一共有多少种满足要求的算式。
    请填写该数字,通过浏览器提交答案,不要填写多余内容(例如:列出所有算式)。

import java.util.HashSet;

public class Main {
	
/*	分两种情况枚举,
	1.一位数和三位数。
	2.两位数和两位数。
	利用HashSet元素不重复的特性。*/
	
	public static void main(String[] args) {
		int mul = 0;
		//第一种情况。
		int N1 = 0;
		for (int i = 1; i < 10;i++) {
			for (int j = 100; j < 1000; j++) {
					//相乘的得数
					mul = i*j;
					//留意:mul小于1000的情况要排去。当其m小于1000时,千位数上会视为0带入运算,导致结果有误。
					if (mul> 1000) {
						HashSet<Integer> set = new HashSet<>();
						set.add(j/100);
						set.add(j%100/10);
						set.add(j%10);
						set.add(i);
						
						HashSet<Integer> match = new HashSet<>();
						match.add(mul/1000);
						match.add(mul/100%10);
						match.add(mul%100/10);
						match.add(mul%10);
						//利用HashSet元素不重复的特性.元素个数有四个即无重复元素。
						if (match.size()==4 && set.size()==4) {
							if (set.containsAll(match)) {
								N1++;
							}
						}
					}
			}
		}
		
		//第二种情况,同理。
		int N2 = 0;
		for (int i = 10; i < 100; i++) {
			for (int j = 10; j < 100; j++) {
				HashSet<Integer> set = new HashSet<>();
				set.add(i/10);
				set.add(i%10);
				set.add(j/10);
				set.add(j%10);
				mul = i*j;
				HashSet<Integer> match = new HashSet<>();
				match.add(mul/1000);
				match.add(mul/100%10);
				match.add(mul%100/10);
				match.add(mul%10);
				if (match.size()==4 && set.size()==4) {
					if (set.containsAll(match)) {
						N2++;
					}
				}
			}
		}
		//两位数和两位数枚举结果必然重复一次,故取一半。
		N2 = N2/2;
		System.out.println(N1+N2);
	}
}


第四题:

标题:写日志
    写日志是程序的常见任务。现在要求在 t1.log, t2.log, t3.log 三个文件间轮流写入日志。也就是说第一次写入t1.log,第二次写入t2.log,... 第四次仍然写入t1.log,如此反复。
    下面的代码模拟了这种轮流写入不同日志文件的逻辑。

public class A
{
	private static int n = 1;
	
	public static void write(String msg)
	{
		String filename = "t" + n + ".log";
		n = ____________;
		System.out.println("write to file: " + filename + " " + msg);
	}
}
    请填写划线部分缺失的代码。通过浏览器提交答案。
注意:不要填写题面已有的内容,也不要填写任何说明、解释文字。
 n = n%3+1;


第五题:


标题:锦标赛
   如果要在n个数据中挑选出第一大和第二大的数据(要求输出数据所在位置和值),使用什么方法比较的次数最少?我们可以从体育锦标赛中受到启发。

   如图【1.png】所示,8个选手的锦标赛,先两两捉对比拼,淘汰一半。优胜者再两两比拼...直到决出第一名。
   第一名输出后,只要对黄色标示的位置重新比赛即可。
   下面的代码实现了这个算法(假设数据中没有相同值)。
   代码中需要用一个数组来表示图中的树(注意,这是个满二叉树, 不足需要补齐)。它不是存储数据本身,而是存储了数据的下标。   
   第一个数据输出后,它所在的位置被标识为-1

class A{
   	//a 表示待处理的数据,长度如果不是2的次幂,则不足位置补为-1
	static void pick(int[] a)
	{
		int n = 1;
		while(n<a.length) n *= 2;
		int[] b = new int[2*n-1];
		for(int i=0; i<n; i++){ 
			if(i<a.length) 
				b[n-1+i] = i;
			else
				b[n-1+i] = -1;
		}
		//从最后一个向前处理
		for(int i=b.length-1; i>0; i-=2){
			if(b[i]<0){
				if(b[i-1]>=0)
					b[(i-1)/2] = b[i-1]; 
				else
					b[(i-1)/2] = -1;
			}
			else{
				if(a[b[i]]>a[b[i-1]])
					b[(i-1)/2] = b[i];
				else
					b[(i-1)/2] = b[i-1];
			}
		}	
		//输出树根
		System.out.println(b[0] + ": " + a[b[0]]);	
		//值等于根元素的位置需要重新pk
		pk(a,b,0,b[0]);	
		//再次输出树根
		System.out.println(b[0] + ": " + a[b[0]]);
	}
	// a 表示待处理数据,b 二叉树,k 当前要重新比拼的位置,v 已经决胜出的值	
   	static void pk(int[] a, int[] b, int k, int v)
	{
		
		int k1 = k*2+1;
		int k2 = k1 + 1;
		
		if(k1>=b.length || k2>=b.length){
			b[k] = -1;
			return;
		}
		if(b[k1]==v) 
			pk(a,b,k1,v);
		else
			pk(a,b,k2,v);
		//重新比较
		if(b[k1]<0){
			if(b[k2]>=0)
				b[k] = b[k2]; 
			else
				b[k] = -1;
			return;
		}
		
		if(b[k2]<0){
			if(b[k1]>=0)
				b[k] = b[k1]; 
			else
				b[k] = -1;
			return;
		}
		if(__________________________)  //填空
			b[k] = b[k1];
		else
			b[k] = b[k2];
	}
}
    请仔细分析流程,填写缺失的代码。
    通过浏览器提交答案,只填写缺失的代码,不要填写已有代码或其它说明语句等。


b[2n-1]代表的就是整个二叉树的数组,用于存放a[]的下标。

b[2n-1]最低层就是a[]数组~通过用 -1 来填充未满二叉树的部分。

将b[2n-1]数组每两个相邻的进行对比,不断往上推算,最后得到的吧b[0]就是存放a[]中最大值的下标。

因为还要求出第二大的值,所以最后还要将根节点的两个子节点进行pk。

a[b[k1]]>a[b[k2]]


第六题:



标题:六角填数
    如图【1.png】所示六角形中,填入1~12的数字。
    使得每条直线上的数字之和都相同。
    图中,已经替你填好了3个数字,请你计算星号位置所代表的数字是多少?
请通过浏览器提交答案,不要填写多余的内容。

import java.util.Arrays;

public class Main {
	//交换数组元素
	public static void swap(int[] array,int numA,int numB){
		int temp;
		temp = array[numA];
		array[numA] = array[numB];
		array[numB] = temp;
	}
	//全排列算法
	public static void permutate(int[] array, int flag, int len){
		//递归到最后一个数输出。
		if(flag == len-1){
			//判断六条边上的的和是否相等。
			if (8+array[0]+array[1]+array[2] == 8+array[3]+array[6]+3
					&& 8+array[0]+array[1]+array[2] == 1+array[0]+array[3]+array[5]
					&& 8+array[0]+array[1]+array[2] == 1+array[1]+array[4]+array[8]
					&& 8+array[0]+array[1]+array[2] == array[2]+array[4]+array[7]+3
					&& 8+array[0]+array[1]+array[2] == array[2]+array[4]+array[7]+3
					&& 8+array[0]+array[1]+array[2] == array[5]+array[6]+array[7]+array[8]
									){
				//输出该*号位置的代表数组值。
				System.out.println(array[3]);//System.out.println(Arrays.toString(array));
			}
		}else {
			for (int i = flag; i < array.length; i++) {
				swap(array, flag, i);
				permutate(array, flag+1, len);
				swap(array, flag, i);
			}
		}
	}
	public static void main(String[] args) {
		int[] a = {2,4,5,6,7,9,10,11,12};
		permutate(a,0,a.length);
	}
}

输出为10。

将六角星的每个空位当成一个数组,即int[] a = {2,4,5,6,7,9,10,11,12};

通过将数组全排列得到每一种情况,并判断是否符合题目要求,六边和相等。

如果输出整个符合的数组的话,应为[9, 2, 7, 10, 12, 6, 5, 4, 11]。

*号位置代表的是array[3] = 10;

这里的关键是 全排列算法



第七题:

标题:绳圈
    今有 100 根绳子,当然会有 200 个绳头。
    如果任意取绳头两两配对,把所有绳头都打结连接起来。最后会形成若干个绳圈(不考虑是否套在一起)。
    我们的问题是:请计算最后将形成多少个绳圈的概率最大?
    注意:结果是一个整数,请通过浏览器提交该数字。不要填写多余的内容。

 

参考:http://www.ylzx8.cn/kaifayuyan/program/404078.html


第八题:


标题:兰顿蚂蚁
    兰顿蚂蚁,是于1986年,由克里斯·兰顿提出来的,属于细胞自动机的一种。
    平面上的正方形格子被填上黑色或白色。在其中一格正方形内有一只“蚂蚁”。
    蚂蚁的头部朝向为:上下左右其中一方。
    蚂蚁的移动规则十分简单:
    若蚂蚁在黑格,右转90度,将该格改为白格,并向前移一格;
    若蚂蚁在白格,左转90度,将该格改为黑格,并向前移一格。
    规则虽然简单,蚂蚁的行为却十分复杂。刚刚开始时留下的路线都会有接近对称,像是会重复,但不论起始状态如何,蚂蚁经过漫长的混乱活动后,会开辟出一条规则的“高速公路”。
    蚂蚁的路线是很难事先预测的。
    你的任务是根据初始状态,用计算机模拟兰顿蚂蚁在第n步行走后所处的位置。
【数据格式】
输入数据的第一行是 m n 两个整数(3 < m, n < 100),表示正方形格子的行数和列数。
接下来是 m 行数据。
每行数据为 n 个被空格分开的数字。0 表示白格,1 表示黑格。
接下来是一行数据:x y s k, 其中x y为整数,表示蚂蚁所在行号和列号(行号从上到下增长,列号从左到右增长,都是从0开始编号)。s 是一个大写字母,表示蚂蚁头的朝向,我们约定:上下左右分别用:UDLR表示。k 表示蚂蚁走的步数。
输出数据为两个空格分开的整数 p q, 分别表示蚂蚁在k步后,所处格子的行号和列号。
例如, 输入:
5 6
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
2 3 L 5
程序应该输出:
1 3
再例如, 输入:
3 3
0 0 0
1 1 1
1 1 1
1 1 U 6
程序应该输出:
0 0

资源约定:
峰值内存消耗(含虚拟机) < 256M CPU消耗  < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

import java.util.Scanner;

public class Main {
	//步数
	static int step = 0;
	//蚂蚁当前坐标值
	static int Y = 0;
	static int X = 0;
	//当前方向
	static String direction = null;
	public static void run(int[][] array){
		if (array[Y][X]==0){
			array[Y][X] =1;
			switch (direction) {
			case "U":
				X--;direction = "L";
				break;
			case "D":
				X++;direction = "R";
				break;
			case "L":
				//值得小心注意的是,因为数组是从上往下排的,所以往下移动的时候反而是Y++。
				Y++;direction = "D";
				break;
			case "R":
				Y--;direction = "U";
				break;
			default:
				break;
			}
		}
		else{
			array[Y][X]=0;
			switch (direction) {
			case "U":
				X++;direction = "R";
				break;
			case "D":
				X--;direction = "L";
				break;
			case "L":
				Y--;direction = "U";
				break;
			case "R":
				Y++;direction = "D";
				break;
			default:
				break;
			}
		}
	}
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int row = sc.nextInt();//行数
		int col = sc.nextInt();//列数
		int[][] matrix = new int[row][col];
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				matrix[i][j] = sc.nextInt();
			}
		}
		Y=sc.nextInt();
		X=sc.nextInt();
		direction = sc.next();
		step = sc.nextInt();
		for (int i = 0; i < step; i++) {
			run(matrix);
		}
		System.out.println(Y+" "+X);
	}
}
这题作为第八题会不会觉得比较奇怪,简单了点。。


第九题:

标题:斐波那契
    斐波那契数列大家都非常熟悉。它的定义是:
    f(x) = 1                    .... (x=1,2)
    f(x) = f(x-1) + f(x-2)      .... (x>2)
    对于给定的整数 n 和 m,我们希望求出:
    f(1) + f(2) + ... + f(n)  的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
    公式参见【图1.png】
    但这个数字依然很大,所以需要再对 p 求模。
【数据格式】
输入为一行用空格分开的整数 n m p (0 < n, m, p < 10^18)
输出为1个整数
例如,如果输入:
2 3 5
程序应该输出:
0

再例如,输入:
15 11 29
程序应该输出:
25

资源约定:
峰值内存消耗(含虚拟机) < 256M CPU消耗  < 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。


我只想到了递归的方法来算,应该会超时。

查了一下别人的方法,大家参考这个:http://blog.csdn.net/ronnoc/article/details/22209365

第十题:

参考:http://www.tuicool.com/articles/7NZrIz

 

因为个人专业原因,自从上次笔试后,

不断忙于去补计算机网络,操作系统,算法数据结构等内容,

待我变得更强时,必回来把几道参考别人答案的也自己编出来分析,让大家更容易懂。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值