2020年 第11届 蓝桥杯 Java B组 省赛真题详解及小结【第1场省赛 2020.7.5】


  • 注意:部分代码及程序 源自 蓝桥杯 官网视频(历年真题解析) 郑未老师
  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.7.5】【Java版】
  11. 2020年 第11届 蓝桥杯 Java B组 省赛真题详解及小结【第1场省赛 2020.7.5】
  12. 2020年 第11届 蓝桥杯 Java C组 省赛真题详解及小结【第1场省赛 2020.7.5】

目   录

一、试题 A: 解密

解法一:手工计算

解法二:编程计算 indexOf()+substring()

二、试题 B: 纪念日

解法一:使用“计算器”求解

解法二:使用“日期类”求解(SimpleDateFormat+Date)

解法三:使用“日期类”求解(Date)

三、试题 C: 合并检测

解法一

解法二

解法三:代码求解

四、试题 D: 分配口罩

五、试题 E: 斐波那契数列最大公约数

六、试题F: 分类计数

解法一:'A' <= temp[i] && temp[i] <= 'Z'

解法二:Character.isUpperCase(a[i])

七、试题G: 八次求和

解法一:BigInteger求解

解法二:快速位运算

八、试题 H: 字符串编码

解法一(有误!!!)

解法二

解法三(精简版)

解法四

九、试题 I: BST 插入节点问题

十、试题 J: 网络分析

小结


试题下载:【链接:https://pan.baidu.com/s/1zgZfxpflhQywaRRNGoi-dg   提取码:zjxs 】

   

一、试题 A: 解密

本题总分:5 分

【问题描述】

小明设计了一种文章加密的方法:对于每个字母 c,将它变成某个另外的字符 Tc。下表给出了字符变换的规则:

                                    

例如,将字符串 YeRi 加密可得字符串 EaFn。

小明有一个随机的字符串,加密后为

EaFnjISplhFviDhwFbEjRjfIBBkRyY

(由 30 个大小写英文字母组成,不包含换行符),请问原字符串是多少?

(如果你把以上字符串和表格复制到文本文件中,请务必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 str.txt,第一行为上面的字符串,后面 52 行依次为表格中的内容。)

【答案提交】

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

【答案】:YeRikGSunlRzgDlvRwYkXkrGWWhXaA

解法一:手工计算

【解析】:观察表可得:a->y、A->Y;建议:5个字母 5个字母地一一进行对比。

解法二:编程计算 indexOf()+substring()

package provincialGames_11_2020;

public class _01_A_解密 {
	public static void main(String[] args) { // 30个字符
//		String res = "YeRik GSunl RzgDl vRwYk XkrGW WhXaA"; // 未加密【答案】
//		String str = "EaFnj ISplh FviDh wFbEj RjfIB BkRyY"; // 加密后
		String str = "EaFnjISplhFviDhwFbEjRjfIBBkRyY"; // 加密后的字符
		char[] arr = str.toCharArray();
		String s1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 原字符
		String s2 = "yxmdacikntjhqlgoufszpwbrevYXMDACIKNTJHQLGOUFSZPWBREV"; // 加密后的字符
		String s3 = ""; // 解密后的字符
		for (int i = 0; i < arr.length; i++) {
			int j = s2.indexOf(arr[i]);   // 输出当前字符在加密后字符中的位置
			s3 += s1.substring(j, j + 1); // 找出原字符在此位置对应的字符
		}
		System.out.println(s3);
	}
}

二、试题 B: 纪念日

本题总分:5 分

【问题描述】

2020 年 7 月 1 日是中国共产党成立 99 周年纪念日。

中国共产党成立于 1921 年 7 月 23 日。

请问从 1921 年 7 月 23 日中午 12 时到 2020 年 7 月 1 日中午 12 时一共包含多少分钟?

【答案提交】

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

【答案】:52038720 

解法一:使用“计算器”求解

       

解法二:使用“日期类”求解(SimpleDateFormat+Date)

  

package provincialGames_11_2020;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class _02_B_纪念日2 {
	// 不需要非要找12点,因为都是从0点算也是一样的
	public static void main(String[] args) throws ParseException {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Date date1 = format.parse("1921-7-23");
		Date date2 = format.parse("2020-7-1");
		int a = (int) ((date2.getTime() - date1.getTime()) / (1000 * 60));
		System.out.println(a);
	}
}

解法三:使用“日期类”求解(Date)

  

package provincialGames_11_2020;

import java.util.Date;

public class _02_B_纪念日 {
	public static void main(String[] args) {
		long sum = 36138 * 24 * 60L;
		System.out.println(sum);
		System.out.println(36138 * 24 * 60);
		// long型变量在定义的时候,如果不加“L”,则默认为int型变量
		Date date1 = new Date(21, 7, 23, 12, 0, 0); // 1921
		Date date2 = new Date(120, 7, 1, 12, 0, 0); // 2020
		long time = date2.getTime() - date1.getTime();
		System.out.println(time / (60000));
	}
}

三、试题 C: 合并检测

本题总分:10 分

【问题描述】

新冠疫情由新冠病毒引起,最近在 A 国蔓延,为了尽快控制疫情,A 国准备给大量民众进病毒核酸检测。

然而,用于检测的试剂盒紧缺。

为了解决这一困难,科学家想了一个办法:合并检测。即将从多个人(k 个)采集的标本放到同一个试剂盒中进行检测。如果结果为阴性,则说明这 k 个人都是阴性,用一个试剂盒完成了 k 个人的检测。如果结果为阳性,则说明至少有一个人为阳性,需要将这 k 个人的样本全部重新独立检测(从理论上看,如果检测前 k − 1 个人都是阴性可以推断出第 k 个人是阳性,但是在实际操作中不会利用此推断,而是将 k 个人独立检测),加上最开始的合并检测,一共使用了 k + 1 个试剂盒完成了 k 个人的检测。

A 国估计被测的民众的感染率大概是 1%,呈均匀分布。请问 k 取多少能最节省试剂盒?

【答案提交】

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

【答案】:10

解法一

这题数学问题
设总人数为pop,感染率p,每次k人,总市级数sum
sum = ( [pop / k]+1 ) * ( 1+k*p(k+1) )
这里的[ pop / k ] + 1,即pop/k向上取整
[pop/k] + 1 这里由于pop数量较大,所以这里向上取整的1可以忽略,这里直接取了pop/k,即
sum = ( pop / k ) * ( 1 + kp( k+1 ) )
将p代入sum = (pop/k)*( 1+k*0.01( k+1 ) )
sum求导 = ( pop/k ) ( 0.01k-1/k)
可得当k =10时,sum取最小值
所以K = 10。

解法二

原文链接

假设A国有n个人,感染者有n/100
每k个人一组,共n/k组,共用n/k瓶试剂
按照最坏的情况,每多出一个感染者就多用k瓶试剂,
因此共用n/k+(n/100)*k瓶试剂
n是定值,所以求(1/k+k/100)最小
由于a+b>=2√ab
当且仅当a = b时,取等号
即1/k=k/100时,取得最小值
解得k = 10

解法三:代码求解

package provincialGames_11_2020;

public class _03_C_合并检测 {
	public static void main(String[] args) {
		int min = 999990;
		int ans = -1;
		for (int i = 1; i <= 100; i++) { // i个人一块测
			int temp;
			if (100 % i != 0) {
				temp = 100 / i + i + 1;
			} else {
				temp = 100 / i + i;
			}
			if (min > temp) {
				min = temp;
				ans = i;
			}
		}
		System.out.println(ans);
	}
}

四、试题 D: 分配口罩

本题总分:10 分

【问题描述】

某市市长获得了若干批口罩,每一批口罩的数目如下:(如果你把以下文字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 mask.txt,内容与下面的文本相同)

9090400

8499400

5926800

8547000

4958200

4422600

5751200

4175600

6309600

5865200

6604400

4635000

10663400

8087200

4554000

现在市长要把口罩分配给市内的 2 所医院。由于物流限制,每一批口罩只能全部分配给其中一家医院。市长希望 2 所医院获得的口罩总数之差越小越好。请你计算这个差最小是多少?

【答案提交】

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

【答案】:2400       仅供参考

package provincialGames_11_2020;

import java.util.Scanner;

public class _04_D_分配口罩2 { // 2400

	static int sum = 0;
	static int[] dp = new int[98090000];
	static int[] nums = { 0, 9090400, 8499400, 5926800, 8547000, 4958200, 4422600,
			5751200, 4175600, 6309600, 5865200, 6604400, 4635000, 10663400, 8087200, 4554000 };

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		for (int i = 1; i < nums.length; i++)
			sum += nums[i];
		int v = sum / 2;
		for (int i = 1; i < nums.length; i++) {
			for (int j = v; j >= nums[i]; j--) {
				dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
			}
		}
		System.out.println(dp[v]);
		System.out.println(sum - 2 * dp[v]);
	}

}

五、试题 E: 斐波那契数列最大公约数

本题总分:15 分

【问题描述】

斐波那契数列满足 F1 = F2 = 1,从 F3 开始有 Fn = Fn−1 + Fn−2。请你计算 GCD(F2020, F520),其中 GCD(A, B) 表示 A 和 B 的最大公约数。

【答案提交】

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

【答案】:6765       仅供参考

package provincialGames_11_2020_1_JavaB;

import java.math.BigInteger;

public class _05_E_斐波那契数列最大公约数 { // 6765

	public static void main(String[] args) {
		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]);
		}
		for (int i = 1; i <= 7; i++) { // 输出斐波那契数组的元素值 验证
			System.out.println(i + ": " + arr[i]);
		}
		System.out.println(arr[520]);
		System.out.println(arr[2020]);
		System.out.println(arr[2020].mod(arr[520]));
//		System.out.println(gcd(arr[2020], arr[520]));
		System.out.println(arr[2020].gcd(arr[520]));
	}

	public static BigInteger gcd(BigInteger a, BigInteger b) {
		return b.equals(BigInteger.ZERO) ? a : gcd(b, a.mod(b));
//		if (b.compareTo(BigInteger.ZERO) == 0) {
//			return a;
//		}
//		return gcd(b, a.mod(b));
	}

}

六、试题F: 分类计数

【问题描述】

输入一个字符串,请输出这个字符串包含多少个大写字母,多少个小写字母,多少个数字。

【输入格式】

输入一行包含一个字符串。

【输出格式】

输出三行,每行一个整数,分别表示大写字母、小写字母和数字的个数。

【样例输入】

1+a=Aab

【样例输出】

1 3 1

【评测用例规模与约定】

对于所有评测用例,字符串由可见字符组成,长度不超过 100。

解法一:'A' <= temp[i] && temp[i] <= 'Z'

package provincialGames_11_2020;

import java.util.Scanner;

public class _06_F_分类计数 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str = sc.next();
		char[] temp = str.toCharArray();
		int upper = 0, lower = 0, digit = 0;
		for (int i = 0; i < temp.length; i++) {
			if ('A' <= temp[i] && temp[i] <= 'Z') {
				upper++;
			} else if ('a' <= temp[i] && temp[i] <= 'z') {
				lower++;
			} else if ('0' <= temp[i] && temp[i] <= '9') {
				digit++;
			}
		}
		System.out.println(upper + " " + lower + " " + digit);
	}

}

解法二:Character.isUpperCase(a[i])

package provincialGames_11_2020_1_JavaB;

import java.util.Scanner;

public class _06_F_分类计数2 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		String s = in.nextLine();
		char[] a = s.toCharArray();
		int upper = 0, lower = 0, num = 0;
		for (int i = 0; i < a.length; i++) {
			if (Character.isUpperCase(a[i]))
				upper++;
			else if (Character.isLowerCase(a[i]))
				lower++;
			else if (Character.isDigit(a[i]))
				num++;
		}
		System.out.print(upper + " " + lower + " " + num);
	}

}

七、试题G: 八次求和

时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分

【问题描述】

给定正整数 n, 求 1^{8}2^{8} + · · · + n^{8} mod 123456789 。其中 mod 表示取余。

【输入格式】

输入的第一行包含一个整数 n。

【输出格式】

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

【样例输入】

2

【样例输出】

257

【样例输入】

987654

【样例输出】

43636805

【评测用例规模与约定】

对于 20% 的评测用例,1 ≤ n ≤ 20。

对于 60% 的评测用例,1 ≤ n ≤ 1000。

对于所有评测用例,1 ≤ n ≤ 1000000。

解法一:BigInteger求解

package provincialGames_11_2020;

import java.math.BigInteger;
import java.util.Scanner;

public class _07_G_八次求和 {

	public static final BigInteger mod = BigInteger.valueOf(123456789);

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt(); // 对于所有评测用例,1 ≤ n ≤ 1000000。
		BigInteger sum = BigInteger.ZERO; // sum会爆int\long
		for (int i = 1; i <= n; i++) {
			BigInteger temp = BigInteger.valueOf(i);
			sum = sum.add(temp.multiply(temp).multiply(temp).multiply(temp).
					multiply(temp).multiply(temp).multiply(temp).multiply(temp));
//			sum = sum.mod(mod);
		}
		System.out.println(sum.mod(mod));
	}

}
/**
int temp = (int) Math.pow(i, 8);
String str = temp + "";
long sum = 0;
for (int i = 1; i <= n; i++) {
	sum += (long)Math.pow(i, 8);
	sum %= mod;
	System.out.println(i + ": " + sum);
}
*/

解法二:快速位运算

 

package provincialGames_11_2020_1_JavaB;

import java.util.Scanner;

public class _07_G_八次求和2 {

	static long mod = 123456789;

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		long n = in.nextLong();
		long ans = 0;
		for (long i = 1; i <= n; i++) {
			ans = (ans + quickPow(i, 8)) % mod;
		}
		System.out.println(ans);
	}

	static long quickPow(long a, int b) {
		long ans = 1;
		while (b > 0) {
			if ((b & 1) == 1)
				ans = (ans * a) % mod;
			a = (a * a) % mod;
			b >>= 1;
		}
		return ans;
	}

}

八、试题 H: 字符串编码

时间限制: 1.0s 内存限制: 512.0MB 本题总分:25 分

【问题描述】

小明发明了一种给由全大写字母组成的字符串编码的方法。对于每一个大写字母,小明将它转换成它在 26 个英文字母中序号,即 A → 1, B → 2, ... Z → 26。

这样一个字符串就能被转化成一个数字序列:

比如 ABCXYZ → 123242526。

现在给定一个转换后的数字序列,小明想还原出原本的字符串。当然这样的还原有可能存在多个符合条件的字符串。小明希望找出其中字典序最大的字符串。

【输入格式】

一个数字序列。

【输出格式】

一个只包含大写字母的字符串,代表答案。

【样例输入】

123242526

【样例输出】

LCXYZ

【评测用例规模与约定】

对于 20% 的评测用例,输入的长度不超过 20。

对于所有评测用例,输入的长度不超过 200000。

   ASCII码表

解法一(有误!!!)

注意:此题解有误!!!部分样例不过关!!!请看题解二!!!

package provincialGames_11_2020;

public class _08_H_字符串编码2 { // 123242526 -> LCXYZ 【部分样例不过关!】

	public static void main(String[] args) {
		java.util.Scanner sc = new java.util.Scanner(System.in);
		String s = sc.nextLine();
		char c[] = s.toCharArray();
		String res = "";
		for (int i = 0; i < c.length - 1;) {
			int temp = (c[i] - '0') * 10 + (c[i + 1] - '0');
			if (temp <= 26) {
				res += ((char) ((temp - 1) + 'A'));
				c[i] = '0';
				c[i + 1] = '0';
				i += 2;
			} else {
				res += ((char) ((temp / 10 - 1) + 'A'));
				i++;
			}
		}
		if (c[c.length - 1] != '0') {
			s += c[c.length - 1];
		}
		System.out.println(res);
	}

}
/**
// c[c.length - 1]:字符数组的倒数第1个字符
// c[c.length - 2]:字符数组的倒数第2个字符
// c[c.length - 3]:字符数组的倒数第3个字符

	public static void main(String[] args) {
		java.util.Scanner sc = new java.util.Scanner(System.in);
		String s = sc.nextLine();
		char c[] = s.toCharArray();
		String b = "";
		for (int i = 0; i < c.length - 1;) { // 遍历字符数组(最后一个字符并未遍历,防止数组越界!)
			int temp = (c[i] - '0') * 10 + (c[i + 1] - '0'); // 字符转数字
			if (temp <= 26) {
				b += ((char) ((temp - 1) + 'A')); // 将数字转化为对应的字符
				i += 2;
//				c[i] = '0';
//				if (i != c.length - 2) { // 如果字符c[i+1]是字符数组的最后一个字符
//				}
//				c[i + 1] = '0';
			} else {
				b += ((char) ((temp / 10 - 1) + 'A')); // 将数字转化为对应的字符
				i++;
			}
		}
		if (c.length >= 3) { // 符合此条件,则字符数组的最后一个字符一定需要转化为字母
			int temp23 = (c[c.length - 3] - '0') * 10 + (c[c.length - 2] - '0'); // 倒数第2、3个字符合并
			int temp12 = (c[c.length - 2] - '0') * 10 + (c[c.length - 1] - '0'); // 倒数第1、2个字符合并
			if (temp23 >= 26) {
				b += ((char) ((temp23 - 1) + 'A')); // 将数字转化为对应的字符
			}
		}
		System.out.println(b);
	}
*/

解法二

原文链接

package provincialGames_11_2020;

import java.util.Scanner;

public class _08_H_字符串编码 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.next();
		sc.close();
		StringBuilder sb = new StringBuilder(); // 答案

		int len = s.length();
		char[] num = s.toCharArray();
		for (int i = 0; i < len; i++) {
			// 1开头
			if (num[i] == '1') {
				// 第i+2位是否为0,如果为0,当前位就不能和i+1位合并成一个字母
				if (i < len - 2) {
					// 不为0
					if (num[i + 2] != '0') {
//                        System.out.println((num[i]-'0') * 10 + num[i + 1] + 'A' -1 -'0' );
						sb.append((char) ((num[i] - '0') * 10 + num[i + 1] + 'A' - 1 - '0'));
						++i;
						// 为0,当前位就不能和i+1位合并成一个字母,(如果合成字母,剩下一个0没办法转换)
					} else {
						sb.append((char) (num[i] - '0' + 'A' - 1));
					}
					// i+2已超过尽头
				} else {
					// 看i+1位是否存在
					if (i < len - 1) {

						sb.append((char) ((num[i] - '0') * 10 + num[i + 1] + 'A' - 1 - '0'));
						// 不存在,第i位为最后一位
					} else {
						sb.append((char) (num[i] - '0' + 'A' - 1));
					}
					break;
				}
				// 2开头
			} else if (num[i] == '2') {
				// 看存不存在下一位
				if (i < len - 1) {
					// 看下一位是不是小于6,因为字母的大小不能超过26
					if (num[i + 1] <= '6') {
						// 看第i+2位是否存在
						if (i < len - 2) {
							// 看第i+2位是否=0
							if (num[i + 2] != '0') {
								sb.append((char) ((num[i] - '0') * 10 + num[i + 1] + 'A' - 1 - '0'));
								++i;
								// 为0,当前位就不能和i+1位合并成一个字母,(如果合成字母,剩下一个0没办法转换)
							} else {
								sb.append((char) (num[i] - '0' + 'A' - 1));
							}
							// 不存在的话,就直接添加就行
						} else {
							sb.append((char) ((num[i] - '0') * 10 + num[i + 1] + 'A' - 1 - '0'));
							break;
						}
						// 如果大于6,证明不能和后一位合并
					} else {
						sb.append((char) (num[i] - '0' + 'A' - 1));
					}
					// 不存在下一位,这一位就直接放进去
				} else {
					sb.append((char) (num[i] - '0' + 'A' - 1));
				}
				// 如果大于2的话,就直接添加就行,字母没有2以上开头的
			} else {
				sb.append((char) (num[i] - '0' + 'A' - 1));
			}
		}
		System.out.println(sb.toString());
	}

	public static char getUppLetter(int num) {
		System.out.println((char) (num));
		return (char) (num);
	}

}

解法三(精简版)

原文链接

package provincialGames_11_2020;

import java.util.Scanner;

public class _08_H_字符串编码3 {

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		String s = input.next();
		int len = s.length();
		char[] c = s.toCharArray();
		int i;
		for (i = 0; i < len - 1; i++) {
			int a = c[i] - '0';
			int b = c[i + 1] - '0';
			int ans = a * 10 + b;
			if (ans < 27) {
				char ch = (char) (ans + 64);
				System.out.print(ch);
				i++;
			} else {
				char ch = (char) (a + 64);
				System.out.print(ch);
			}
		}
		if (i < len) {
			char ch = (char) (c[i] - '0' + 64);
			System.out.print(ch);
		}
	}

}

解法四

package provincialGames_11_2020_1_JavaB;

import java.util.Scanner;

public class _08_H_字符串编码4 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		String s = in.nextLine();
		char[] a = s.toCharArray();
		boolean[] vis = new boolean[a.length];
		char[] ans = new char[a.length];
		int cnt = 0, tmp;
		for (int i = 0; i < a.length - 1; i++) {
			tmp = (a[i] - '0') * 10 + a[i + 1] - '0';
			if (tmp <= 26) {
				ans[cnt++] = (char) ('A' + tmp - 1);
				vis[i] = vis[i + 1] = true;
				i++;
			} else {
				ans[cnt++] = (char) ('A' + a[i] - '0' - 1);
				vis[i] = true;
			}
		}
		if (!vis[a.length - 1])
			ans[cnt++] = (char) ('A' + a[a.length - 1] - '0' - 1);
		for (int i = 0; i < cnt; i++)
			System.out.print(ans[i]);
	}

}

九、试题 I: BST 插入节点问题

时间限制: 1.0s 内存限制: 512.0MB 本题总分:25 分

【问题描述】

给定一棵包含 N 个节点的二叉树,节点编号是 1 ∼ N。其中 i 号节点具有权值 W_{i},并且这些节点的权值恰好形成了一棵排序二叉树 (BST)。

现在给定一个节点编号 K,小明想知道,在这 N 个权值以外,有多少个整数 X (即 X 不等于任何 W_{i} ) 满足:给编号为 K 的节点增加一个权值为 X 的子节点,仍可以得到一棵 BST。

例如在下图中,括号外的数字表示编号、括号内的数字表示权值。即编号 1 ∼ 4 的节点权值依次是 0、10、20、30。

如果 K = 1,那么答案为 0。因为 1 号节点已经有左右子节点,不能再增加子节点了。

如果 K = 2,那么答案为无穷多。因为任何一个负数都可以作为 2 的左子节点。

如果 K = 3,那么答案为 9。因为 X = 11, 12, · · · , 19 都可以作为 3 的左子节点。

【输入格式】

第一行包含 2 个整数 N 和 K。

以下 N 行每行包含 2 个整数,其中第 i 行是编号为 i 的节点的父节点编号 Pi 和权值 W_{i} 。注意 Pi = 0 表示 i 是根节点。

输入保证是一棵 BST。

【输出格式】

一个整数代表答案。如果答案是无穷多,输出 −1。

【样例输入】

4 3

0 10

1 0

1 20

3 30

【样例输出】

9

【评测用例规模与约定】

对于 60% 的评测用例,1 ≤ K ≤ N ≤ 100,0 ≤ W_{i} ≤ 200,且 W_{i} 各不相同。

对于所有评测用例,1 ≤ K ≤ N ≤ 10000,0 ≤ W_{i} ≤ 100000000,且 W_{i} 各不相同。

原文链接

package provincialGames_11_2020;

import java.util.Scanner;

public class _09_I_BST插入节点问题 {
	
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();
		int k = input.nextInt();
		int a[] = new int[100100];
		int b[] = new int[100100];
		int vis[] = new int[100010];
		for (int i = 1; i <= n; i++) {
			a[i] = input.nextInt();
			b[i] = input.nextInt();
			vis[i] = a[i];
		}
		int cnt = 0;
		int ans = 0;
		for (int i = 1; i <= n; i++) {
			if (vis[i] == k) {
				cnt++;
				ans = b[i];
			}
		}
		if (cnt == 2)
			System.out.print(0);
		else if (cnt == 1) {
			ans = Math.abs(ans - b[k]);
			System.out.print(ans - 1);
		} else
			System.out.print(-1);
	}
	
}

十、试题 J: 网络分析

时间限制: 1.0s 内存限制: 256.0MB 本题总分:25 分

【问题描述】

小明正在做一个网络实验。

他设置了 n 台电脑,称为节点,用于收发和存储数据。

初始时,所有节点都是独立的,不存在任何连接。

小明可以通过网线将两个节点连接起来,连接后两个节点就可以互相通信了。两个节点如果存在网线连接,称为相邻。

小明有时会测试当时的网络,他会在某个节点发送一条信息,信息会发送到每个相邻的节点,之后这些节点又会转发到自己相邻的节点,直到所有直接或间接相邻的节点都收到了信息。所有发送和接收的节点都会将信息存储下来。一条信息只存储一次。

给出小明连接和测试的过程,请计算出每个节点存储信息的大小。

【输入格式】

输入的第一行包含两个整数 n, m,分别表示节点数量和操作数量。节点从 1 至 n 编号。

接下来 m 行,每行三个整数,表示一个操作。

如果操作为 1 a b,表示将节点 a 和节点 b 通过网线连接起来。当 a = b 时,表示连接了一个自环,对网络没有实质影响。

如果操作为 2 p t,表示在节点 p 上发送一条大小为 t 的信息。

【输出格式】

输出一行,包含 n 个整数,相邻整数之间用一个空格分割,依次表示进行完上述操作后节点 1 至节点 n 上存储信息的大小。

【样例输入】

4 8

1 1 2

2 1 10

2 3 5

1 4 1

2 2 2

1 1 2

1 2 4

2 2 1

【样例输出】

13 13 5 3

【评测用例规模与约定】

对于 30% 的评测用例,1 ≤ n ≤ 20,1 ≤ m ≤ 100。

对于 50% 的评测用例,1 ≤ n ≤ 100,1 ≤ m ≤ 1000。

对于 70% 的评测用例,1 ≤ n ≤ 1000,1 ≤ m ≤ 10000。

对于所有评测用例,1 ≤ n ≤ 10000,1 ≤ m ≤ 100000,1 ≤ t ≤ 100。

package provincialGames_11_2020;

import java.util.LinkedList;
import java.util.Scanner;

public class _10_J_网络分析 {

	static int[] data;
	static boolean[] bool;
	static LinkedList<LinkedList<Integer>> list = new LinkedList<LinkedList<Integer>>();

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		data = new int[n + 1];
		bool = new boolean[n + 1];
		int a = 0, b = 0, c = 0;
		for (int i = 0; i <= n; i++) {
			list.add(new LinkedList<>());
		}
		for (int i = 0; i < m; i++) {
			a = sc.nextInt();
			b = sc.nextInt();
			c = sc.nextInt();
			// 网络题把他们互相联系起来
			if (a == 1) {
				list.get(b).add(c);
				list.get(c).add(b);
			} else {
				bool = new boolean[n + 1];
				dfs(b, c);
			}
		}
		for (int i = 1; i <= n; i++) {
			System.out.print(data[i] + " ");
		}
	}

	// dfs遍历每一个结点
	public static void dfs(int node, int num) {
		bool[node] = true;
		data[node] += num;
		LinkedList<Integer> templist = list.get(node);
		for (int i : templist) {
			if (!bool[i]) {
				dfs(i, num);
			}
		}
	}

}

小结

仔细、认真,注意日期类、大整数BigInteger的使用。

猜你喜欢

转载自blog.csdn.net/weixin_44949135/article/details/108228625