2021年 第12届 蓝桥杯 第4次模拟赛真题详解及小结【Java版】


  1. 2013年 第04届 蓝桥杯 Java B组 省赛真题详解及小结
  2. 2014年 第05届 蓝桥杯 Java B组 省赛真题详解及小结
  3. 2015年 第06届 蓝桥杯 Java B组 省赛真题详解及小结
  4. 2016年 第07届 蓝桥杯 Java B组 省赛真题详解及小结
  5. 2017年 第08届 蓝桥杯 Java B组 省赛真题详解及小结
  6. 2018年 第09届 蓝桥杯 Java B组 省赛真题详解及小结
  7. 2019年 第10届 蓝桥杯 Java B组 省赛真题详解及小结
  8. 2020年 第11届 蓝桥杯 第1次模拟赛真题详解及小结【Java版】(校内模拟)// 官方讲解视频
  9. 2020年 第11届 蓝桥杯 第2次模拟赛真题详解及小结【Java版】// 官方讲解视频
  10. 2020年 第11届 蓝桥杯 C/C++ B组 省赛真题详解及小结【第1场省赛 2020.07.05】【Java版】
  11. 2020年 第11届 蓝桥杯 Java B组 省赛真题详解及小结【第1场省赛 2020.07.05】
  12. 2020年 第11届 蓝桥杯 Java B组 省赛真题详解及小结【第2场省赛 2020.10.17】
  13. 2020年 第11届 蓝桥杯 Java C组 省赛真题详解及小结【第1场省赛 2020.07.05】
  14. 2021年 第12届 蓝桥杯 第1次模拟赛真题详解及小结【Java版】
  15. 2021年 第12届 蓝桥杯 第2次模拟赛真题详解及小结【Java版】
  16. 2021年 第12届 蓝桥杯 第3次模拟赛真题详解及小结【Java版】
  17. 2021年 第12届 蓝桥杯 第4次模拟赛真题详解及小结【Java版】
  18. 2021年 第12届 蓝桥杯 Java B组 省赛真题详解及小结

  1. 2015年 第06届 蓝桥杯 Java B组 决赛真题详解及小结
  2. 2016年 第07届 蓝桥杯 Java B组 决赛真题详解及小结
  3. 2017年 第08届 蓝桥杯 Java B组 决赛真题详解及小结
  4. 2018年 第09届 蓝桥杯 Java B组 决赛真题详解及小结
  5. 2019年 第10届 蓝桥杯 Java B组 决赛真题详解及小结
  6. 2020年 第11届 蓝桥杯 Java B组 决赛真题详解及小结

目录

模拟赛网页截图

一、试题A——答案:P

解法一:ASCII码值对应的字符

二、试题B——答案:16

解法一:质数判断

三、试题C——答案:4042

解法一:二叉树节点的求解

四、试题D——答案:25

解法一:找规律

解法二:BigInteger数组遍历

五、试题E——答案:8

解法一

六、试题F

解法一

七、试题G

解法一

八、试题H

解法一

九、试题I

解法一

十、试题J

解法一

小结


仅供参考,欢迎指正!以下均为个人想法和解题思路,如有错误或不足,欢迎指正。

模拟赛网页截图

 

一、试题A——答案:P

问题描述

  ASCII 码将每个字符对应到一个数值(编码),用于信息的表示和传输。在 ASCII 码中,英文字母是按从小到大的顺序依次编码的,例如:字母 A 编码是 65, 字母 B 编码是 66,字母 C 编码是 67,请编码为 80 的是哪个字母?

答案提交

  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个英文字母,在提交答案时只填写这个英文字母,填写多余的内容将无法得分。

解法一:ASCII码值对应的字符

【答案】:P

【解析】:递推,直接 解出 ASCII码值 对应的字符 即可!

package simulationMatch_12_2021_4;

public class _01A {
	public static void main(String[] args) {
		System.out.println('A' - 0); // 65
		System.out.println('B' - 0); // 66
		System.out.println('C' - 0); // 67
		System.out.println('P' - 0); // 80
		System.out.println('Q' - 0); // 81
		System.out.println('Q' + 0); // 81
		System.out.println('Z' - 0); // 90
	}
}

二、试题B——答案:16

问题描述

  请问在 1900 到 2020 中,有多少个质数。

答案提交

  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

解法一:质数判断

【答案】:16

【解析】:for循环遍历数据[1900, 2020],根据“质数的定义”进行求解,枚举计数。

package simulationMatch_12_2021_4;

public class _02B {
	public static void main(String[] args) {
		int answer = 0;
		for (int i = 1900; i <= 2020; i++) {
			if (testIsPrime(i)) {
				answer++;
			}
		}
		System.out.println(answer);
	}

	public static boolean testIsPrime(int n) {
		if (n <= 3) {
			return n > 1;
		}
		for (int i = 2; i < n; i++) {
			if (n % i == 0)
				return false;
		}
		return true;
	}

	/* 优化后 */
	public static boolean testIsPrime2(int n) {
		if (n <= 3) {
			return n > 1;
		}
		for (int i = 2; i <= Math.sqrt(n); i++) {
			if (n % i == 0)
				return false;
		}
		return true;
	}
}

三、试题C——答案:4042

问题描述

  有一棵二叉树,有2021个叶结点。
  请问。这棵树至少有多少个结点?

答案提交

  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

解法一:二叉树节点的求解

【答案】:4042

【解析】:

  • 非空二叉树上的叶子结点数(度为0的节点,称为“叶子结点”)等于度为2的结点数加1,即 n_{0} = n_{2} + 1 。
  • 设度为0、1、2的结点个数分别为n_{0}n_{1}n_{2},二叉树的节点总数 n = n_{0} + n_{1} + n_{2} 。

二叉树的总结点个数为:n = n_{0} + n_{1} + n_{2} = n_{0} + n_{1} + \left ( n_{0} - 1 \right )

度为2的结点数 n2 = n0 - 1 = 2021 - 1 = 2020

叶子节点的数目为2021个(奇数),所以肯定存在度为1的节点,即 n1 = 1 。

所以,二叉树的总结点个数至少为:n = n_{0} + n_{1} + n_{2} = n_{0} + n_{1} + \left ( n_{0} - 1 \right ) = 2021 + 1 + 2020 = 4042

对于这棵二叉树,最少的节点数目为只有度数为0和度数为2的节点,但是因为叶子节点的数目为2021个(奇数个),所以肯定存在度为1的节点,那么,最终二叉树总的节点数目为 n = n0 + n1 + n2 = 2021 + 1 + 2020 = 4042个节点。

四、试题D——答案:25

问题描述

  Fibonacci序列按照如下公式定义:
  F[1] = 1
  F[2] = 1
  F[i] = F[i-1] + F[i-2] (i>2)
  前几个 Fibonacci 数为 1, 1, 2, 3, 5, 8, 13, 21。
  请问,前100个 Fibonacci 数中,有多少个数是 3 的倍数?

答案提交

  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

解法一:找规律

原文链接:百度知道——在斐波那契数列的前100个数中有多少个数是三的倍数?

多写几个找规律:1、1、2、3、5、8、13、21、34、55、89、144 ...
会发现每4个数中,会出现一个3的倍数。所以,前100个数中,3的倍数有:100÷4=25个。

解法二:BigInteger数组遍历

【答案】:25

【解析】:遍历Fibonacci序列——Fibonacci序列的第100项数据,会爆“int型数组、long型数组”,所以要使用BigInteger数组。

package simulationMatch_12_2021_4;

import java.util.Arrays;
import java.math.BigInteger;

public class _04D {

	public static void main(String[] args) {
//		test1();
//		test2();
		test3();
	}

	public static void test1() { //测试:fib[100]爆int数组
		int fib[] = new int[105];
		fib[0] = 0;
		fib[1] = fib[2] = 1;
		for (int i = 3; i <= 102; i++) {
			fib[i] = fib[i - 1] + fib[i - 2];
		}
		int answer = 0;
		for (int i = 1; i <= 100; i++) {
			if (fib[i] % 3 == 0) {
				answer++;
				System.out.print(i + "、");
			}
		}
		System.out.println("\n" + answer);
		System.out.println(Arrays.toString(fib));
	}

	public static void test2() { //测试:fib[100]爆long数组
		long fib[] = new long[102];
		fib[0] = 0;
		fib[1] = fib[2] = 1;
		for (int i = 3; i < 102; i++) {
			fib[i] = fib[i - 1] + fib[i - 2];
			System.out.println(i + ":" + fib[i]);
		}
//		System.out.println(Arrays.toString(fib));
		int answer = 0;
		for (int i = 1; i <= 100; i++) {
			if (fib[i] % 3 == 0) {
				answer++;
				System.out.print(i + "、");
			}
		}
		System.out.println("\n" + answer);
	}

	public static void test3() {
		BigInteger arr[] = new BigInteger[2025]; // int型与long型数据均会爆数组
		arr[0] = BigInteger.ZERO;
		arr[1] = arr[2] = BigInteger.ONE;
		for (int i = 3; i <= 2020; i++) {
			arr[i] = arr[i - 1].add(arr[i - 2]);
		}
		int answer = 0;
		BigInteger three = new BigInteger("3");
		for (int i = 1; i <= 100; i++) { // 输出斐波那契数组的元素值 验证
			System.out.println(i + ": " + arr[i]);
			if (arr[i].mod(three).equals(arr[0])) {
				answer++;
//				System.out.print(i + "、");
			}
		}
		System.out.println("\n" + answer);
	}

}

五、试题E——答案:8

问题描述

  一个身份证号码有 18 位数字或字母组成。其中前17位必须是数字,最后一位可能是数字或字母X。
  身份证号码满足一定的校验规则。
  令身份证号从右到左依次标号为 1 到 18,其中标号为 i 的位的位权设置为 2^(i-1) mod 11 (2的i-1次方除以 11 的余数)。
  将每一位的数值乘以位权相加,得到的结果除以 11 的余数应当为 1。其中最后一位(标号为1)中如果出现字母 X,看成数字 10。
  例如,如果一个人的身份证号为 34052419800101001X,则:
  标号为 1 的位,位权 1,数值 X,即 10,相乘得 10。
  标号为 2 的位,位权 2,数值 1,相乘得 2。
  标号为 3 的位,位权 4,数值 0,相乘得 0。
  标号为 4 的位,位权 8,数值 0,相乘得 0。
  标号为 5 的位,位权 5,数值 1,相乘得 5。
  标号为 6 的位,位权 10,数值 0,相乘得 0。
  标号为 7 的位,位权 9,数值 1,相乘得 9。
  标号为 8 的位,位权 7,数值 0,相乘得 0。
  标号为 9 的位,位权 3,数值 0,相乘得 0。
  标号为 10 的位,位权 6,数值 8,相乘得 48。
  标号为 11 的位,位权 1,数值 9,相乘得 9。
  标号为 12 的位,位权 2,数值 1,相乘得 2。
  标号为 13 的位,位权 4,数值 4,相乘得 16。
  标号为 14 的位,位权 8,数值 2,相乘得 16。
  标号为 15 的位,位权 5,数值 5,相乘得 25。
  标号为 16 的位,位权 10,数值 0,相乘得 0。
  标号为 17 的位,位权 9,数值 4,相乘得 36。
  标号为 18 的位,位权 7,数值 3,相乘得 21。
  将乘积相加,得 199,除以 11 的余数正好为 1。
  小明的身份证号前 17 位为 11010120210221999,请问小明身份证的最后一位是多少?

答案提交

  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个字符,可能是数字或者大写字母X,在提交答案时只填写这个字符,填写多余的内容将无法得分。

解法一

【答案】:8

【解析】:1 ≤ i ≤ 18

 

package simulationMatch_12_2021_4;

public class _05E {

	public static void main(String[] args) {
//		System.out.println(Integer.MAX_VALUE); // 2147483647
//		System.out.println(Long.MAX_VALUE); // 9223372036854775807 19位
//		System.out.println('0' - '0');
//		System.out.println('1' - '0');

		calculate("34052419800101001X"); // 199 1

		// 将每一位的数值乘以位权后相加,得到的结果除以 11 的余数应当为 1。
//		calculate("110101202102219990");
//		calculate("110101202102219991");
//		calculate("110101202102219992");
//		calculate("110101202102219993");
//		calculate("110101202102219994");
//		calculate("110101202102219995");
//		calculate("110101202102219996");
//		calculate("110101202102219997");
		calculate("110101202102219998"); // 221 1【答案:8】
//		calculate("110101202102219999");
//		calculate("11010120210221999X");
	}

	public static void calculate(String num) {
		StringBuilder sb = new StringBuilder(num);
		sb = sb.reverse();
		char[] charArray = sb.toString().toCharArray(); // 先转String再转字符数组
		int sum = 0;
		for (int i = 0; i < 18; i++) {
			if (i == 0) { // 计算首位
				if (charArray[0] == 'X') {
					sum += 10;
				} else {
					int place = (int) Math.pow(2, i) % 11;// 标号为 i 的位的位权设置为 2^(i-1) mod 11
					System.out.println(i + "---" + place + "---" + charArray[i] + "---" + ((int) (charArray[i] - '0') * place));
					sum += (int) (charArray[i] - '0') * place; // 将每一位的数值乘以位权后相加
				}
			} else { // 计算非首位
				int place = (int) Math.pow(2, i) % 11;// 标号为 i 的位的位权设置为 2^(i-1) mod 11
				System.out.println(i + "---" + place + "---" + charArray[i] + "---" + ((int) (charArray[i] - '0') * place));
				sum += (int) (charArray[i] - '0') * place; // 将每一位的数值乘以位权后相加
			}
//			System.out.println(sum + "\n\n");
		}
		System.out.println(sum);
		System.out.println(sum % 11);
	}

}

六、试题F

问题描述

小Hi的公司经常举办回馈社会的爱心活动。这次小Hi作为志愿者带领社区的孩子们参观了青少年天文馆。他发现孩子们对于摩尔斯电码非常感兴趣。

摩尔斯电码由两种基本的信号组成:短信号"滴"(用字符'.'表示)以及长信号"嗒"(用字符'-'表示)。下图是数字0-9的摩尔斯电码表示,每个数字都由5个字符组成:

.---- ..--- ...-- ....- ..... -.... --... ---.. ----. -----
1     2     3     4     5     6     7     8     9     0

为了让孩子们开心,小Hi决定把每位孩子的生日日期转化为摩尔斯码赠送给他们。例如日期20210101对应的摩尔斯电码是:

..--- ----- ..--- .---- ----- .---- ----- .----

你能写一个程序帮助小Hi吗?

输入格式

第一行是一个整数N,代表参加活动的孩子的人数。(1 <= N <= 100)

以下N行每行一个由0-9组成的字符串,代表一个生日日期。(日期格式:yyyymmdd,日期范围: 20000101至20210101)

输出格式

对于每个生日日期,输出一行表示转化后的摩尔斯码,数字之间用一个空格隔开。

样例输入

2  
20161011  
20000101

样例输出

..--- ----- .---- -.... .---- ----- .---- .----
..--- ----- ----- ----- ----- .---- ----- .----

解法一

【解析】:最好将‘0’对应的字符串,设置在字符串数组的开头位置!

package simulationMatch_12_2021_4;

import java.util.Scanner;

public class _06F {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt(); // 1 <= N <= 100
		String str[] = { "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----." }; // 0对应的字符串在开头
		for (int i = 1; i <= N; i++) { // 由0-9组成的字符串,日期范围:20000101至20210101
			String s = sc.next();
			char strArray[] = s.toCharArray();
			for (int j = 0; j < 8; j++) { // [0, 8] 遍历字符数组,取出每一个字符
				int index = (int) (strArray[j] - '0'); // 字符串数组的下标
				if (j == 7) { // 若是输出最后的字符串,则末尾不加空格
					System.out.print(str[index]);
				} else {
					System.out.print(str[index] + " ");
				}
			}
			System.out.println();
		}
	}
}

七、试题G

问题描述

  小蓝在商店买文具。
  一支钢笔 x 元,小蓝买了 a 支。
  一个笔记本 y 元,小蓝买了 b 本。
  请问,小蓝一共需要支付多少钱?

输入格式

  输入四行。
  第一行包含一个整数 x。
  第二行包含一个整数 a。
  第三行包含一个整数 y。
  第四行包含一个整数 b。

输出格式

  输出一个整数,表示答案。

样例输入

5
2
1
6

样例输出

16

样例输入

2
0
2
1

样例输出

2

数据规模和约定

  对于所有评测用例,0 <= x, a, y, b <= 100。

解法一

package simulationMatch_12_2021_4;

import java.util.Scanner;

public class _07G {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int x = sc.nextInt();
		int a = sc.nextInt();
		int y = sc.nextInt();
		int b = sc.nextInt();
		System.out.println(x * a + y * b);
	}

}

八、试题H

问题描述

  给定一个序列 (a_1, a_2, ..., a_n), 定义序列中的一个递增三元组是指三个下标 i, j, k 对应的三个元素 a_i, a_j, a_k,这三个元素满足 a_i < a_j < a_k。
  例如序列 (1, 1, 4, 3, 2, 4) 有以下 4 个递增三元组:
  1. 下标 1, 4, 6 对应的 1, 3, 4;
  2. 下标 1, 5, 6 对应的 1, 2, 4;
  3. 下标 2, 4, 6 对应的 1, 3, 4;
  4. 下标 2, 5, 6 对应的 1, 2, 4。
  注意,可能有下标不同,但对应数值相同的三元组,他们应当算成不同的三元组。
  给定序列,请问序列中一共有多少个不同的递增三元组。

输入格式

  输入第一行包含一个整数 n,表示序列的长度。
  第二行包含 n 个整数 a_1, a_2, ..., a_n,表示给定的序列。

输出格式

  输出一行,包含一个整数,表示序列中的递增三元组数量。请注意答案可能很大,可能超过 32 位二进制整数的范围,建议使用 64 位二进制整数。

样例输入

6
1 1 4 3 2 4

样例输出

4

数据规模和约定

  对于 30% 的评测用例,1 <= n <= 20, 0 <= a_i <= 10。
  对于 50% 的评测用例,1 <= n <= 1000, 0 <= a_i <= 100。
  对于 80% 的评测用例,1 <= n <= 10000, 0 <= a_i <= 100。
  对于所有评测用例,1 <= n <= 100000, 0 <= a_i <= 100。

解法一

【解析】:三个元素满足 a_i < a_j < a_k

for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                for (int k = j + 1; k < n; k++) {

package simulationMatch_12_2021_4;

import java.util.Arrays;
import java.util.Scanner;

public class _08H {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int array[] = new int[n + 1];
		for (int i = 0; i < n; i++) {
			array[i] = sc.nextInt();
		}
//		System.out.println(Arrays.toString(array));
		Long answer = 0L; // 答案可能很大,建议使用64位二进制整数
		for (int i = 0; i < n; i++) {
			for (int j = i + 1; j < n; j++) {
				for (int k = j + 1; k < n; k++) {
					if (array[i] < array[j] && array[j] < array[k]) {
						answer++;
					}
				}
			}
		}
		System.out.println(answer);
	}

}

九、试题I

问题描述

  小Hi正在研究一种特殊的栈。这种栈的元素既可以从栈顶出栈,也可以从栈底出栈。(进栈还是只能从栈顶进栈)
  已知入栈的序列是1~N的一个排列,请你判断出栈序列能否是1, 2, 3, ... N?

输入格式

  输入包含多组数据。
  输入第一行包含一个整数T,代表测试数据的组数。
  以下每组数据占据2行。
  第一行包含一个整数N。
  第二行包含N个整数,整数中由空格隔开。表示入栈序列。

输出格式

  对于每组数据输出YES或者NO,代表出栈序列能否是1, 2, 3, ... N。

样例输入

2
5
2 4 1 3 5
5
4 3 1 5 2

样例输出

YES
NO

数据规模和约定

  对于30%的评测用例,1 <= N <= 10
  对于80%的评测用例,1 <= N <= 10000
  对于所有评测用例,1 <= N <= 100000, 1 <= T <= 10。

解法一

求巨佬支招!

十、试题J

问题描述

  给定两个序列 A=(a_1, a_2, ..., a_n) 和 B=(b_1, b_2, ..., b_m), 它们的一个公共子序列是指从两个序列中分别取出相同个数的元素,按照原来的顺序排列后,对应位置的数值相等。
  例如,对于序列 A=(3, 2, 7, 6, 7) 和 B=(2, 3, 5, 7),可以在序列 A 中取出第 2, 3 个元素,在序列 B 中取出第 1, 4 个元素,值都是 2, 7,因此 2, 7 是一个公共子序列,在 A 中取第 2, 3 个元素和在 B 中取 1, 4 个元素是这个公共子序列的一种取法。
  在这两个序列中,有 4 中取法可以取出长度为 2 的公共子序列,例如
  1. 在 A 中取第 1, 3 个元素,在 B 中取 2, 4 个元素;
  1. 在 A 中取第 1, 5 个元素,在 B 中取 2, 4 个元素;
  1. 在 A 中取第 2, 3 个元素,在 B 中取 1, 4 个元素;
  1. 在 A 中取第 2, 5 个元素,在 B 中取 1, 4 个元素。
  给定两个序列,请问有多少种取法可以取出长度为 k 的公共子序列。

输入格式

  输入第一行包含三个整数 n, m, k,分别表示序列 A 的长度、序列 B 的长度和公共子序列的长度。
  第二行包含 n 个整数 a_1, a_2, ..., a_n,表示给定的 A 序列。
  第三行包含 m 个整数 b_1, b_2, ..., b_m,表示给定的 B 序列。

输出格式

  输出一行,包含一个整数,表示长度为 k 的公共子序列的数量,答案可能很大,请输出答案除以 1000007 的余数。

样例输入

5 4 2
3 2 7 6 7
2 3 5 7

样例输出

4

数据规模和约定

  对于 30% 的评测用例,1 <= n, m <= 20。
  对于 50% 的评测用例,1 <= n, m <= 100。
  对于所有评测用例,1 <= n, m <= 1000, 1 <= k <= 10, 0 <= a_i <= 100。

解法一

求巨佬支招!

小结

手写计算的题目,可以“编程+计算”进行求解验证。
蓝桥杯比赛时,时间紧迫,在保证正确率的情况下,写快一些,然后多检查几遍。

蓝桥杯 斐波那契数列前100项,BigInteger数组模板

猜你喜欢

转载自blog.csdn.net/weixin_44949135/article/details/115434665
今日推荐