第十二届蓝桥杯 2021年国赛真题 (Java 大学B组)
Posted 肖有量
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第十二届蓝桥杯 2021年国赛真题 (Java 大学B组)相关的知识,希望对你有一定的参考价值。
蓝桥杯 2021年国赛真题(Java 大学 B 组 )
认真整下,不嘻嘻哈哈了。
#A 整数范围
本题总分:5 分
问题描述
用 8 8 8 位二进制(一个字节)来表示一个非负整数,表示的最小值是 0 0 0,则一般能表示的最大值是多少?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
255
calcCode:
public class Test {
public static void main(String[] args) {
System.out.print(0xFF);
}
}
?
#B 纯质数
本题总分:5 分
问题描述
如果一个正整数只有
1
1
1 和它本身两个约数,则称为一个质数(又称素数)。
前几个质数是:
2
,
3
,
5
,
7
,
11
,
13
,
17
,
19
,
23
,
29
,
31
,
37
,
⋅
⋅
⋅
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, · · ·
2,3,5,7,11,13,17,19,23,29,31,37,⋅⋅⋅ 。
如果一个质数的所有十进制数位都是质数,我们称它为纯质数。例如:
2
,
3
,
5
,
7
,
23
,
37
2, 3, 5, 7, 23, 37
2,3,5,7,23,37 都是纯质数,而
11
,
13
,
17
,
19
,
29
,
31
11, 13, 17, 19, 29, 31
11,13,17,19,29,31 不是纯质数。当然
1
,
4
,
35
1, 4, 35
1,4,35 也不是纯质数。
请问,在
1
1
1 到
20210605
20210605
20210605 中,有多少个纯质数?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
1903
预备知识
如果不会一种合数筛法的,估计跑到比赛结束结果都出不来。
质数打表,
就是为了这点题解,
我才写的这篇博客。
就是为了这篇博客,
我才立的这个标题。
朴素解法
一种朴素的想法,在打表 [ 1 , 20210605 ] [1,20210605] [1,20210605] 间的质数时,额外的进行一次纯质数效验,并将结果累加起来。
import java.util.ArrayList;
import java.util.List;
public class Test {
public static final int N = 20210605;
public static void main(String[] args) {
boolean[] marked = new boolean[N + 1];
List<Integer> primes = new ArrayList();
marked[0] = marked[1] = true;
int ans = 0;
for (int i = 2; i <= N; i++) {
if (!marked[i]) {
primes.add(i);
boolean flag = false;
for (int k = i; k > 0; k /= 10)
if (flag = marked[k % 10]) break;
if (!flag) ans++;
}
for (int p : primes) {
if (p * i > N) break;
marked[p * i] = true;
if (i % p == 0) break;
}
}
System.out.println(ans);
}
}
按位枚举
在朴素的解法中,我们会发现,很多拆分判断一个质数是否是纯质数是没有必要的,因为在 [ 0 , 10 ) [0,10) [0,10) 中,质数仅占 { 2 , 3 , 5 , 7 } \\{2,3,5,7\\} {2,3,5,7} 四位,如果仅判断这四个数字组合成的数是否是质数的话,性能能否有进一步的提升呢?
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Test {
public static final int N = 20210605;
public static int[][] digits = new int[8][4];
public static void main(String[] args) {
boolean[] primes = new boolean[N + 1];
List<Integer> helper = new ArrayList();
Arrays.fill(primes, 2, N, true);
int ans = 0;
for (int i = 2; i <= N; i++) {
if (primes[i]) helper.add(i);
for (int p : helper) {
if (p * i > N) break;
primes[p * i] = false;
if (i % p == 0) break;
}
}
digits[0] = new int[]{2, 3, 5, 7};
for (int k = 1; k < 7; k++)
for (int i = 0; i < 4; i++)
digits[k][i] = digits[k - 1][i] * 10;
digits[7] = new int[]{ digits[6][0] * 10 };
System.out.println(dfs(primes, 0, 0));
}
public static int dfs(boolean[] primes, int k, int depth) {
if (depth == 8) return k <= N && primes[k] ? 1 : 0;
int ans = primes[k] ? 1 : 0;
for (int a : digits[depth])
ans += dfs(primes, k + a, depth + 1);
return ans;
}
}
实际上性能并没有进一步的提升,并且代码量还有所增加。
这是因为在 ( 1 , N ] (1,N] (1,N] 这个范围中的质数大约有 N ln N \\cfrac{N}{\\ln N} lnNN 个,而按位组成的可能是纯质数的数大约有 4 ln N 4^{\\ln N} 4lnN 个,这显然不是一个增值量级的。
但这里放这么一段代码,是为了进一步扩展刷题较少的读者的解题思路,能掌握一种方法来解决其他的问题。
#C 完全日期
本题总分:10 分
问题描述
如果一个日期中年月日的各位数字之和是完全平方数,则称为一个完全日期。
例如:
2021
2021
2021 年
6
6
6 月
5
5
5 日的各位数字之和为
2
+
0
+
2
+
1
+
6
+
5
=
16
2 + 0 + 2 + 1 + 6 + 5 = 16
2+0+2+1+6+5=16,而
16
16
16 是一个完全平方数,它是
4
4
4 的平方。所以
2021
2021
2021 年
6
6
6 月
5
5
5 日是一个完全日期。
例如:
2021
2021
2021 年
6
6
6 月
23
23
23 日的各位数字之和为
2
+
0
+
2
+
1
+
6
+
2
+
3
=
16
2 + 0 + 2 + 1 + 6 + 2 + 3 = 16
2+0+2+1+6+2+3=16,是一个完全平方数。所以
2021
2021
2021 年
6
6
6 月
23
23
23 日也是一个完全日期。
请问,从
2001
2001
2001 年
1
1
1 月
1
1
1 日到
2021
2021
2021 年
12
12
12 月
31
31
31 日中,一共有多少个完全日期?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
977
Java党的完全胜利
LocalDate
好用。
朴素解法
枚举 [ 2001 [2001 [2001- 01 01 01- 01 01 01, 2021 2021 2021- 12 12 12- 31 ] 31] 31] 这个区间间内的时间,判断然后累加。
import java.time.LocalDate;
public class Test {
public static final int maxPerfect = 2 + 0 + 1 + 9 + 0 + 9 + 2 + 9;
public static final boolean[] perfect = new boolean[maxPerfect + 1];
public static LocalDate start = LocalDate.of(2001, 01, 01);
public static LocalDate end = LocalDate.of(2021, 12, 31);
public static void main(String[] args) {
int count = 0;
for (int i = 1; i * i<= maxPerfect; i++)
perfect[i * i] = true;
while (end.compareTo(start) >= 0) {
if (perfect[calc(start)])
count++;
start = start.plusDays(1);
}
System.out.println(count);
}
public static int calc(LocalDate date) {
String dateStr = date.toString();
int res = 0;
for (int i = dateStr.length() - 1; i >= 0; i--)
if (Character.isDigit(dateStr.charAt(i)))
res += Character.digit(dateStr.charAt(i), 10);
return res;
}
}
朴素改进
在 [ 2001 [2001 [2001- 01 01 以上是关于第十二届蓝桥杯 2021年国赛真题 (Java 大学B组)的主要内容,如果未能解决你的问题,请参考以下文章