第十三届蓝桥杯大赛软件赛省赛 Java题解集合

赛题下载查看免费0积分下载。
https://download.csdn.net/download/weixin_43461755/85099936
通过这次比赛,再次打击了我,300块都花了,无论结果怎样,把这次做的题分享出来吧。由于Java比较耗时,我写题解劲量都去测试下极端值(在比赛时没有)

题解还没写完,持续更新中!

试题 A: 排列字母

本题总分:5 分
【问题描述】
小蓝要把一个字符串中的字母按其在字母表中的顺序排列。
例如,LANQIAO 排列后为 AAILNOQ。
又如,GOODGOODSTUDYDAYDAYUP 排列后为 AADDDDDGGOOOOPSTUUYYY

请问对于以下字符串,排列之后字符串是什么?
WHERETHEREISAWILLTHEREISAWAY
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个由大写字母组成的字符串,在提交答案时只填写这个字符串,填写多余的内
容将无法得分。

解题思路:
直接调API排序输出即可。
说长不长,说短不短,靠肉眼去数还有可能数错,写代码还快些。
解题代码:

import java.util.Arrays;

public class Main {
	public static void main(String[] args) {
		String s = "WHERETHEREISAWILLTHEREISAWAY";
		char[] zf = s.toCharArray();
		Arrays.sort(zf);
		System.out.println(zf);
	}
}

答案:AAAEEEEEEHHHIIILLRRRSSTTWWWY

试题 B: 灭鼠先锋

本题总分:5 分
【问题描述】
灭鼠先锋是一个老少咸宜的棋盘小游戏,由两人参与,轮流操作。
灭鼠先锋的棋盘有各种规格,本题中游戏在两行四列的棋盘上进行。游戏
的规则为:两人轮流操作,每次可选择在棋盘的一个空位上放置一个棋子,或
在同一行的连续两个空位上各放置一个棋子,放下棋子后使棋盘放满的一方输
掉游戏。
小蓝和小乔一起玩游戏,小蓝先手,小乔后手。小蓝可以放置棋子的方法
很多,通过旋转和翻转可以对应如下四种情况:
XOOO XXOO OXOO OXXO
OOOO OOOO OOOO OOOO
其中 O 表示棋盘上的一个方格为空,X 表示该方格已经放置了棋子。
请问,对于以上四种情况,如果小蓝和小乔都是按照对自己最优的策略来
玩游戏,小蓝是否能获胜。如果获胜,请用 V 表示,否则用 L 表示。请将四种
情况的胜负结果按顺序连接在一起提交。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个长度为 4 的由大写字母 V 和 L 组成的字符串,如 VVLL,在提交答案时只填
写这个字符串,填写多余的内容将无法得分。

解题思路:
说实话,我题都没读懂,到底是个啥意思额,考语文吗???先跳过,想好了再来写。
解题代码:

先跳过

答案:暂时不知道

试题 C: 质因数个数

时间限制: 5.0s 内存限制: 512.0MB 本题总分:10 分
【问题描述】
给定正整数 n,请问有多少个质数是 n 的约数。
【输入格式】
输入的第一行包含一个整数 n。
【输出格式】
输出一个整数,表示 n 的质数约数个数。
【样例输入】
396
【样例输出】
3
【样例说明】
396 有 2, 3, 11 三个质数约数。
【评测用例规模与约定】
对于 30% 的评测用例,1 ≤ n ≤ 10000。
对于 60% 的评测用例,1 ≤ n ≤ 109
对于所有评测用例,1 ≤ n ≤ 1016

解题思路:
直接判断 2 到 sqrt(n) 有哪些数是 n 的约数。
1.判断是否是n的约数,是则进入第2步,否则跳过。
2.判断是否是质数。

备注:我在代码里写了计算时间的代码,不需要查看时间自行注释掉即可。

解题代码:

import java.util.HashSet;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		long n = sc.nextLong();
		sc.close();

		// 程序开始运行,计时开始
		long start = System.currentTimeMillis();
		// set保存质因数
		HashSet<Long> set = new HashSet<>();
		for (long i = 2; i < Math.sqrt(n); i++) {
			if (n % i == 0 && IsPrime(i)) {
				set.add(i);
				// 判断商是否也为质因数,例如:10的质因数有2,5.
				// 而判断只从2-sqrt(10)即3,那么5则漏掉了。所以要判断下5是否也为质数
				long shang = n / i;
				if (IsPrime(shang))
					set.add(shang);
			}
		}

		System.out.println(set.size());

		// 程序结束时间
		long end = System.currentTimeMillis();
		// 程序总耗时
		System.out.println("程序运行耗时:" + (end - start) + " ms");
	}

	// 判断是否为素数
	private static boolean IsPrime(long n) {
		if (n <= 3) {
			return n > 1;
		}
		for (long i = 2; i <= Math.sqrt(n); i++) {
			if (n % i == 0)
				return false;
		}
		return true;
	}
}

极端值测试:

在这里插入图片描述在这里插入图片描述在这里插入图片描述

试题 D: 数位排序

时间限制: 1.0s 内存限制: 512.0MB 本题总分:10 分
【问题描述】
小蓝对一个数的数位之和很感兴趣,今天他要按照数位之和给数排序。当
两个数各个数位之和不同时,将数位和较小的排在前面,当数位之和相等时,
将数值小的排在前面。
例如,2022 排在 409 前面,因为 2022 的数位之和是 6,小于 409 的数位
之和 13。
又如,6 排在 2022 前面,因为它们的数位之和相同,而 6 小于 2022。
给定正整数 n,m,请问对 1 到 n 采用这种方法排序时,排在第 m 个的元
素是多少?
【输入格式】
输入第一行包含一个正整数 n。
第二行包含一个正整数 m。
【输出格式】
输出一行包含一个整数,表示答案。
【样例输入】
13
5
【样例输出】
3
【样例说明】
1 到 13 的排序为:1, 10, 2, 11, 3, 12, 4, 13, 5, 6, 7, 8, 9。第 5 个数为 3。
【评测用例规模与约定】
对于 30% 的评测用例,1 ≤ m ≤ n ≤ 300。
对于 50% 的评测用例,1 ≤ m ≤ n ≤ 1000。
对于所有评测用例,1 ≤ m ≤ n ≤ 1016

解题思路:
将数列按照题目要求进行排序,最后输出第m个数即可。

备注:因为我在排序时运用了两个for,时间复杂度就超高了,只能跑过50%的评测用例。

解题代码:

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		sc.close();
		
		// 程序开始运行,计时开始
		long start = System.currentTimeMillis();
		
		int[] nums = new int[n + 1];
		for (int i = 0; i < nums.length; i++) nums[i] = i;
		Sort(nums);
		System.out.println(nums[m]);
		
		// 程序结束时间
		long end = System.currentTimeMillis();
		// 程序总耗时
		System.out.println("程序运行耗时:" + (end - start) + " ms");
	}

	// 将数组按题目格式排序
	private static void Sort(int[] array) {
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array.length; j++) {
				if (bijiao(array[i], array[j]) == true) {
					int temp = array[i];
					array[i] = array[j];
					array[j] = temp;
				}
			}
		}
	}

	// 比较2个数的大小,如:2022,409 返回true
	private static boolean bijiao(int a, int b) {
		int sa = he(a), sb = he(b);
		if (sa < sb)
			return true;
		if ((sa == sb) && a < b)
			return true;
		return false;
	}

	// 统计一个数的和,如:123 ,返回6
	private static int he(int num) {
		String s = String.valueOf(num);
		int sh = 0;
		for (int i = 0; i < s.length(); i++) {
			sh += s.charAt(i) - '0';
		}
		return sh;
	}
}

极端值测试:
在这里插入图片描述 在这里插入图片描述
备注:暂时只能过50%的测试用例。先跳过,有好的思路或想法可以评论下呀。

试题 E: 蜂巢

时间限制: 1.0s 内存限制: 512.0MB 本题总分:15 分
【问题描述】
蜂巢由大量的六边形拼接而成,定义蜂巢中的方向为:0 表示正西方向,1
表示西偏北 60◦,2 表示东偏北 60◦,3 表示正东,4 表示东偏南 60◦,5 表示西
偏南 60◦。
对于给定的一点 O,我们以 O 为原点定义坐标系,如果一个点 A 由 O 点
先向 d 方向走 p 步再向 (d + 2) mod 6 方向(d 的顺时针 120◦ 方向)走 q 步到
达,则这个点的坐标定义为 (d, p, q)。在蜂窝中,一个点的坐标可能有多种。
下图给出了点 B(0, 5, 3) 和点 C(2, 3, 2) 的示意。
在这里插入图片描述

给定点 (d1, p1, q1) 和点 (d2, p2, q2),请问他们之间最少走多少步可以到达?
【输入格式】
输入一行包含 6 个整数 d1, p1, q1, d2, p2, q2 表示两个点的坐标,相邻两个整
数之间使用一个空格分隔。
【输出格式】
输出一行包含一个整数表示两点之间最少走多少步可以到达。
【样例输入】
0 5 3 2 3 2
【样例输出】
7
【评测用例规模与约定】
对于 25% 的评测用例,p1, p2 ≤ 103
对于 50% 的评测用例,p1, p2 ≤ 105
对于 75% 的评测用例,p1, p2 ≤ 107
对于所有评测用例,0 ≤ d1, d2 ≤ 5,0 ≤ q1 < p1 ≤ 109,0 ≤ q2 < p2 ≤ 109

解题思路:
暂时跳过,后面更新。

解题代码:

暂时跳过,后面更新。

试题 F: 爬树的甲壳虫

时间限制: 1.0s 内存限制: 512.0MB 本题总分:15 分
【问题描述】
有一只甲壳虫想要爬上一颗高度为 n 的树,它一开始位于树根,高度为 0,
当它尝试从高度 i − 1 爬到高度为 i 的位置时有 Pi 的概率会掉回树根,求它从
树根爬到树顶时,经过的时间的期望值是多少。
【输入格式】
输入第一行包含一个整数 n 表示树的高度。
接下来 n 行每行包含两个整数 xi, yi,用一个空格分隔,表示 Pi =xi / yi。
【输出格式】
输出一行包含一个整数表示答案,答案是一个有理数,请输出答案对质
数 998244353 取模的结果。其中有理数 a
b 对质数 P 取模的结果是整数 c 满足
0 ≤ c < P 且 c · b ≡ a (mod P)。
【样例输入 1】
1
1 2
【样例输出 1】
2
【样例输入 2】
3
1 2
3 5
7 11
【样例输出 2】
623902744
【评测用例规模与约定】
对于 20% 的评测用例,n ≤ 2,1 ≤ xi < yi ≤ 20 ;
对于 50% 的评测用例,n ≤ 500,1 ≤ xi < yi ≤ 200 ;
对于所有评测用例,1 ≤ n ≤ 100000,1 ≤ xi < yi ≤ 109

解题思路:
暂时跳过,后面更新。

解题代码:

暂时跳过,后面更新。

试题 G: 重新排序

时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分
【问题描述】
给定一个数组 A 和一些查询 Li, Ri,求数组中第 Li 至第 Ri 个元素之和。
小蓝觉得这个问题很无聊,于是他想重新排列一下数组,使得最终每个查询结果的和尽可能地大。小蓝想知道相比原数组,所有查询结果的总和最多可以增加多少?
【输入格式】
输入第一行包含一个整数 n。
第二行包含 n 个整数 A1, A2, · · · , An,相邻两个整数之间用一个空格分隔。
第三行包含一个整数 m 表示查询的数目。
接下来 m 行,每行包含两个整数 Li、Ri ,相邻两个整数之间用一个空格分隔。
【输出格式】
输出一行包含一个整数表示答案。
【样例输入】
5
1 2 3 4 5
2
1 3
2 5
【样例输出】
4
【样例说明】
原来的和为 6 + 14 = 20,重新排列为 (1, 4, 5, 2, 3) 后和为 10 + 14 = 24,增
加了 4。
【评测用例规模与约定】
对于 30% 的评测用例,n, m ≤ 50 ;
对于 50% 的评测用例,n, m ≤ 500 ;
对于 70% 的评测用例,n, m ≤ 5000 ;
对于所有评测用例,1 ≤ n, m ≤ 105,1 ≤ Ai ≤ 106,1 ≤ Li ≤ Ri ≤ 106

解题思路:
暂时跳过,后面更新。

解题代码:

暂时跳过,后面更新。

试题 H: 技能升级

时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分
【问题描述】
小蓝最近正在玩一款 RPG 游戏。他的角色一共有 N 个可以加攻击力的技
能。其中第 i 个技能首次升级可以提升 Ai 点攻击力,以后每次升级增加的点数
都会减少 Bi。⌈Ai/Bi⌉ (上取整) 次之后,再升级该技能将不会改变攻击力。
现在小蓝可以总计升级 M 次技能,他可以任意选择升级的技能和次数。请
你计算小蓝最多可以提高多少点攻击力?
【输入格式】
输入第一行包含两个整数 N 和 M。
以下 N 行每行包含两个整数 Ai 和 Bi。
【输出格式】
输出一行包含一个整数表示答案。
【样例输入】
3 6
10 5
9 2
8 1
【样例输出】
47
【评测用例规模与约定】
对于 40% 的评测用例,1 ≤ N, M ≤ 1000;
对于 60% 的评测用例,1 ≤ N ≤ 104, 1 ≤ M ≤ 107
对于所有评测用例,1 ≤ N ≤ 105,1 ≤ M ≤ 2 × 109,1 ≤ Ai, Bi ≤ 106

解题思路:
1.将小蓝N个技能对应只要可以增加攻击力大于0,将其存放到数组gg;
2.将攻击力gg进行排序;
3.从攻击力gg数组选取最大的M个攻击力加起来返回即可。

解题代码:

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

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[] gg = new int[600000000];
		
		int k = 0;
		for(int i = 0; i < n; i++) {
			int a = sc.nextInt(), b = sc.nextInt();
			//每个技能最多可加的次数
			int cs = 0;
			cs = a % b > 0 ? a / b + 1 : a / b;
			for (int j = 0; j < n; j++) {
				gg[k++] = a;
				a -= b;
				if (a < 0 || cs-- <= 0) break;
			}
		}
		int [] dd = Arrays.copyOfRange(gg, 0, k);
		Arrays.sort(dd);
		long sum = 0;
		for (int u = dd.length-1; u > 0; u--) {
			sum += dd[u];
			m--;
			if(m == 0) break;
		}
		System.out.println(sum);
		sc.close();
	}
}

试题 I: 最优清零方案

时间限制: 3.0s 内存限制: 512.0MB 本题总分:25 分
【问题描述】
给定一个长度为 N 的数列 A1, A2, · · · , AN。现在小蓝想通过若干次操作将
这个数列中每个数字清零。
每次操作小蓝可以选择以下两种之一:

  1. 选择一个大于 0 的整数,将它减去 1;
  2. 选择连续 K 个大于 0 的整数,将它们各减去 1。
    小蓝最少经过几次操作可以将整个数列清零?
    【输入格式】
    输入第一行包含两个整数 N 和 K。
    第二行包含 N 个整数 A1, A2, · · · , AN。
    【输出格式】
    输出一个整数表示答案。
    【样例输入】
    4 2
    1 2 3 4
    【样例输出】
    6
    【评测用例规模与约定】
    对于 20% 的评测用例,1 ≤ K ≤ N ≤ 10。
    对于 40% 的评测用例,1 ≤ K ≤ N ≤ 100。
    对于 50% 的评测用例,1 ≤ K ≤ N ≤ 1000。
    对于 60% 的评测用例,1 ≤ K ≤ N ≤ 10000。
    对于 70% 的评测用例,1 ≤ K ≤ N ≤ 100000。
    对于所有评测用例,1 ≤ K ≤ N ≤ 1000000, 0 ≤ Ai ≤ 1000000。

解题思路:
一次遍历即可。
1.首先判断当前连续K个数是否满足大于0,在这个判断的同时把这K个连续的最小数smin找出来。
2.如果满足连续K个数大于0,则将这K个数都减少这段数中的最小值smin。
3.如果不满足连续K个数大于0,则将这个位置清0,然后回到步骤1即可,直到最后数组全部清空。

备注:我觉得还可以改进,如果这个K个数不连续,则清空这个位置为0,但是我步骤1中已经遍历了K个位置一次,这样到了下个位置我又得重新遍历下一个位置的连续K个位置,有点滑动窗口的感觉,如果用到KMP思想,应该还可以再优化。

解题代码:

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int k = sc.nextInt();
		
//		int[] sz = new int[n];
//		Random random = new Random();
//		for (int i = 0; i < n; i++) sz[i] = random.nextInt(1000000);
		
		int[] sz = new int[n];
		for (int i = 0; i < n; i++) {
			sz[i] = sc.nextInt();
		}
		
		//程序开始运行,计时开始
		System.out.println("输入或随机数组完成,开始计时");
		long start = System.currentTimeMillis();

		System.out.println(qling(sz, k));

		// 程序结束时间
		long end = System.currentTimeMillis();
		// 程序总耗时
		System.out.printf("程序运行耗时:" + (end - start) + " ms" );
		sc.close();
	}
	//将对应位置清0
	private static long qling(int[] nums, int k) {
		long sum = 0;
		for (int j = 0; j < nums.length; j++) {
			int smin = nums[j];
			if (lx(nums, j, k, smin)) {
					qk(nums, j, k, smin);
					sum += smin;
			} else {
				sum += nums[j];
				nums[j] = 0;
			}
		}
		return sum;
	}
	//判断从first开始的K长距离是否连续,同时把这K个阶段的最小最小值找出来
	private static boolean lx(int[] nums, int first, int k, int smin) {
		if (first + k > nums.length)
			return false;
		for (int i = first; i < nums.length; i++) {
			if (nums[i] == 0) return false;
			smin = Math.min(smin, nums[i]);
		}
		return true;
	}
	//从first位置开始连续清空这k个连续位置的最小数smin
	private static void qk(int[] nums, int first, int k, int smin) {
		for (int i = 0; i < k; i++) {
			nums[first++] -= smin;
		}
	}
}

极端值测试
 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述
备注:所以暂时只能通过60%的测试用例,果然是暴力杯呀。

试题 J: 推导部分和

时间限制: 1.0s 内存限制: 512.0MB 本题总分:25 分
【问题描述】
对于一个长度为 N 的整数数列 A1, A2, · · · AN,小蓝想知道下标 l 到 r 的部分和 ∑ri=l = Al + Al+1 + · · · + Ar 是多少?
然而,小蓝并不知道数列中每个数的值是多少,他只知道它的 M 个部分和的值。其中第 i 个部分和是下标 li 到 ri 的部分和 ∑rij=li= Ali + Ali+1 + · · · + Ari ,值是 S i。
【输入格式】
第一行包含 3 个整数 N、M 和 Q。分别代表数组长度、已知的部分和数量
和询问的部分和数量。
接下来 M 行,每行包含 3 个整数 li,ri, S i。
接下来 Q 行,每行包含 2 个整数 l 和 r ,代表一个小蓝想知道的部分和。
【输出格式】
对于每个询问,输出一行包含一个整数表示答案。如果答案无法确定,输
出 UNKNOWN。
【样例输入】
5 3 3
1 5 15
4 5 9
2 3 5
1 5
1 3
1 2

解题思路:
暂时跳过,后面更新。

解题代码:

暂时跳过,后面更新。
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NewGe6

动力源泉:打赏+关注+点赞

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值