2020Java-B组省赛(7月第一场)
一、解密(看)
直接看
答案:YeRikGSunlRzgDlvRwYkXkrGWWhXaA
二、纪念日(SimpleDateFormat类、Date类)
之前几次比赛一直考Calendar类,这次终于考到了Date类,Date类注意要用SimpleDateFormat类转换成Date,yyyy-MM-dd HH:mm:ss,MM是月份(从1开始),mm是分钟,HH是24小时制,hh是12小时制。
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class Main {
public static void main(String[] args) throws ParseException {
// HH是24小时制,MM是月份,mm是分钟,Date月份是从1月份开始,Calendar是从0开始
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date start = sdf.parse("1921-07-23 12:00:00");
Date end = sdf.parse("2020-07-01 12:00:00");
System.out.println((end.getTime() - start.getTime()) / 1000 / 60);
}
}
赛前多看看Date、Calendar类,多半都会用上。
答案:52038720
三、合并检测(公式推导)
新冠疫情由新冠病毒引起,最近在 A 国蔓延,为了尽快控制疫情,A 国准 备给大量民众进病毒核酸检测。
然而,用于检测的试剂盒紧缺。为了解决这一困难,科学家想了一个办法:合并检测。
即将从多个人(k 个)采集的标本放到同一个试剂盒中进行检测。如果结果为阴性,则说明这 k 个人都是阴性,用一个试剂盒完成了 k 个人的检测。
如果结果为阳性,则说明至少有一个人为阳性,需要将这 k 个人的样本全部重新独立检测(从理论上看,如果检测前 k−1 个人都是阴性可以推断出第 k 个人是阳性,但是在实际操作中不会利用此推断,而是将 k 个人独立检测),
加上最开始的合并检测,一共使用 了 k + 1 个试剂盒完成了 k 个人的检测。
A 国估计被测的民众的感染率大概是 1%,呈均匀分布。
请问 k 取多少能 最节省试剂盒?
这是一道结果填空题,你只需要算出结果后提交即可。
本题的结果为一个 整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
注意,如果为阳性,那么k个人需要k+1次检测。假设有100个人,就有1个人是阳性,k=10,那么可以分成10组,每组10人,有阳性的那个组别还需要再测10次 = 10 + 10 = 20(100 / k + k)。而k=9时,分成11组还剩1个人,至于缺少的9个人可以凑,因为实际的人数是不确定的,我们只能往多的考虑,那么必须要12个组才能测完,一旦有一个组是阳性,就还要测9次(100 / k + k + 1)。
找到公式就好办了,直接遍历所有的k,找最小值。
public class Main {
public static void main(String[] args) throws ParseException {
int ans = Integer.MAX_VALUE;
int sum = Integer.MAX_VALUE;
for (int i = 1; i <= 100; i++) {
if (100 % i == 0) {
int tmp = 100 / i + i;
if (tmp < sum) {
ans = i;
sum = tmp;
}
} else {
int tmp = 100 / i + i + 1;
if (tmp < sum) {
ans = i;
sum = tmp;
}
}
}
System.out.println(ans);
}
}
答案:10
四、分配口罩(搜索)
【问题描述】
某市市长获得了若干批口罩,每一批口罩的数目如下:
(如果你把以下文 字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。
在试题目 录下有一个文件 mask.txt,内容与下面的文本相同)
9090400
8499400
5926800
8547000
4958200
4422600
5751200
4175600
6309600
5865200
6604400
4635000
10663400
8087200
4554000
现在市长要把口罩分配给市内的 2 所医院。
由于物流限制,每一批口罩只能全部分配给其中一家医院。
市长希望 2 所医院获得的口罩总数之差越小越好。
请你计算这个差最小是多少?
【答案提交】
这是一道结果填空题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
一共15个数据,直接搜索吧。
import java.util.*;
public class Main {
static int[] nums = new int[15];
static int sum = 0;
static int tmpSum = 0;
static int ans = Integer.MAX_VALUE;
static LinkedList<Integer> tmp = new LinkedList<>();
public static void main(String[] args) {
nums = new int[15];
Scanner scan = new Scanner(System.in);
for (int i = 0; i < 15; i++) {
// 最后都是2个零,可以先去掉
nums[i] = scan.nextInt();
sum += nums[i];
}
dfs(0);
System.out.println(ans);
}
static void dfs(int start) {
if (tmp.size() > 1) {
if (Math.abs(sum - tmpSum - tmpSum) < ans) {
ans = Math.abs(sum - tmpSum - tmpSum);
System.out.println(ans);
}
}
if (tmp.size() > 9) {
return;
}
for (int i = start; i < nums.length; i++) {
tmpSum += nums[i];
tmp.add(nums[i]);
dfs(i + 1);
// 回溯
tmp.removeLast();
tmpSum -= nums[i];
}
}
}
答案:2400
五、斐波那契数列最大公约数(BigInteger类)
把gcd和求斐波那契数列的过程换成BigInteger即可。
import java.math.BigInteger;
import java.util.*;
public class Main {
static BigInteger gcd(BigInteger a, BigInteger b) {
if (b.compareTo(BigInteger.valueOf(0)) == 0) return a;
return gcd(b, a.mod(b));
}
public static void main(String[] args) {
BigInteger[] f = new BigInteger[2021];
f[1] = BigInteger.valueOf(1);
f[2] = BigInteger.valueOf(1);
for (int i = 3; i <= 2020; i++) {
f[i] = f[i - 1].add(f[i - 2]);
System.out.println(f[i]);
}
System.out.println(gcd(f[2020], f[520]));
}
}
答案:6765
六、分类计数(暴力)
送分题…
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String str = scan.nextLine();
int big = 0;
int small = 0;
int num = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) >= '0' && str.charAt(i) <= '9') {
num++;
} else if (str.charAt(i) >= 'a' && str.charAt(i) <= 'z') {
small++;
} else if (str.charAt(i) >= 'A' && str.charAt(i) <= 'Z') {
big++;
}
}
System.out.println(big);
System.out.println(small);
System.out.println(num);
}
}
七、八次求和(BigInteger类)
【问题描述】
给定正整数 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完事啦,1000000也能通过哦。
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
BigInteger mod = BigInteger.valueOf(123456789);
BigInteger sum = BigInteger.valueOf(0);
for (int i = 1; i <= n; i++) {
BigInteger tmp = BigInteger.valueOf(i);
tmp = tmp.pow(8).mod(mod);
sum = sum.add(tmp).mod(mod);
}
System.out.println(sum);
}
}
八、字符串编码(贪心)
注意,本题只关注字典序最大,不用管长度,长度长但是字典序小是没用的。
看当前数字是否大于等于3,是的话就直接加对应的字母;小于3,就要计算后面一位和这一位共同构成的字符(当然要判断是否到了最后一个字符)。
做出上面判断的原因是,题目只要求字典序,那就必须第一个字母足够大,后续的字母也必须要大。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String str = scan.nextLine();
// 最大字典序
String ans = "";
int i = 0;
while (i < str.length()) {
if (str.charAt(i) >= '3') {
ans += (char)(65 + str.charAt(i) - '1');
i++;
} else {
if (i + 1 == str.length()) {
ans += (char)(65 + str.charAt(i) - '1');
i++;
} else {
int tmp = (str.charAt(i) - '0') * 10 + str.charAt(i + 1) - '0';
ans += (char)(65 + tmp - 1);
i += 2;
}
}
}
System.out.println(ans);
}
}
九、BST 插入节点问题
树的问题…还不咋会
十、网络分析