最近回顾了Java B组的试题,深有感触:脑子长时间不用会锈住,很可怕。
兄弟们,都给我从被窝里爬起来,赶紧开始卷!!!
2022年第十三届蓝桥杯Java B组(第一部分 A~F题)
目录
一、填空题
试题 A: 星期计算
思路与题解:
试题 B: 山
思路与题解:
二、编程题
试题 C: 字符统计
思路与题解:
试题 D: 最少刷题数
思路与题解:
试题 E: 求阶乘
思路与题解:
试题 F: 最大子矩阵
思路与题解:
一、填空题
试题 A: 星期计算
本题总分:5 分
【问题描述】
已知今天是星期六,请问 天后是星期几?注意用数字 1 到 7 表示星期一到星期日。【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
思路与题解:
A题显然是个签到题,很多人第一思路就是“取余”,思路没错,但是如果直接暴力取余,那你就格局小了,哥们!
因为20的22次幂(大于2^88)明显不在long类型的范围内【(2^63)-1】,那么就要分步骤做取余运算:
根据公式: (a * b) % p = (a % p * b % p) % p
20^22相当于22个20做了21次乘法运算,所以我的思路是把每一次乘法的结果取余,这样,别说是long可以装得下,就算是int也手拿把掐了!
public static void Java_B_A(){
int n = 20;
for(int i=0;i<21;i++)
n = (20*n)%7;
System.out.println((n+5)%7+1);
}
最终结果:7 ,即星期日。
试题 B: 山
本题总分:5 分
【问题描述】
这天小明正在学数数。他突然发现有些正整数的形状像一座“山”,比如 123565321、145541,它们左右对称(回文)且数位上的数字先单调不减,后单调不增。
小明数了很久也没有数完,他想让你告诉他在区间 [2022, 2022222022] 中有多少个数的形状像一座“山”。【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
思路与题解:
直接暴力遍历,并判断条件,时间有点长但好用。
public static void Java_B_B(){
int sum = 0;
for(int i=2022;i<=2022222022;i++) {
if(isUp(i)&&isMirror(i)) {
sum++;
}
}
System.out.println(sum);
}
public static boolean isMirror(int num){
StringBuffer str = new StringBuffer(num+"");
if((str.toString()).equals(str.reverse().toString()))
return true;
return false;
}
public static boolean isUp(int num){
String st=num+"";
int len=st.length()%2==0?st.length()/2:st.length()/2+1;
for(int i=1;i<len;i++) {
if(st.charAt(i)<st.charAt(i-1)) {
return false;
}
}
return true;
}
最终结果:3138 。
二、编程题
试题 C: 字符统计
时间限制: 1.0s 内存限制: 512.0MB 本题总分:10 分
【问题描述】
给定一个只包含大写字母的字符串 S ,请你输出其中出现次数最多的字母。如果有多个字 母均出现了最多次,按字母表顺序依次输出所有这些字母。【输入格式】
一个只包含大写字母的字符串 S .【输出格式】
若干个大写字母,代表答案。【样例输入】
BABBACAC【样例输出】
AB【评测用例规模与约定】
对于 100% 的评测用例,1 ≤ |S | ≤ .
思路与题解:
本题运用Java的集合框架很容易解决。首先遍历字符串,把其中的每一种字母以键值对<字母种类,出现次数>的形式保存到HashMap中,然后遍历map提取出出现次数最多的n个字母,把它们存到list列表中,利用Collections工具类把list中字母排序,最后输出打印。
public static void Java_B_C(){
Scanner scanner = new Scanner(System.in);
String input = scanner.next();
HashMap<Character, Integer> mp = new HashMap();
for(int i=0;i<input.length();i++){
char ch = input.charAt(i);
if (mp.get(ch) != null)
mp.put(ch, (mp.getOrDefault(ch, 0)) + 1);
else
mp.put(ch, 1);
}
int maxNum = Integer.MIN_VALUE;
List<Character> list = new ArrayList<Character>();
for(Character c:mp.keySet()){
if(mp.get(c)>=maxNum){
maxNum = mp.get(c);
list.add(c);
}
}
Collections.sort(list);
for(Character ch:list){
System.out.print(ch);
}
}
试题 D: 最少刷题数
时间限制: 1.0s 内存限制: 512.0MB 本题总分:10 分
【问题描述】
小蓝老师教的编程课有 N 名学生,编号依次是 1 . . . N。第 i 号学生这学期刷题的数量是 。
对于每一名学生,请你计算他至少还要再刷多少道题,才能使得全班刷题比他多的学生数不 超过刷题比他少的学生数。【输入格式】
第一行包含一个正整数 N。
第二行包含 N 个整数: ,. . . , .【输出格式】
输出 N 个整数,依次表示第 1 . . . N 号学生分别至少还要再刷多少道题。【样例输入】
5
12 10 15 20 6【样例输出】
0 3 0 0 7【评测用例规模与约定】
对于 30% 的数据,1 ≤ N ≤ 1000, 0 ≤ ≤ 1000.
对于 100% 的数据,1 ≤ N ≤ 100000, 0 ≤ ≤ 100000.
思路与题解:
对输入的刷题数进行排序;
分情况考虑:奇数情况下,超过中间值才能满足全班刷题比他多的学生数不超过刷题比他少的学生数;偶数情况下需要等于中间偏大的值就可以满足条件。
public static void Java_B_D() {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int[] nums = new int[n];
int[] count = new int[n];
for (int i = 0; i < nums.length; i++) {
// 输入的一个数组,并把这个数组复制下来
nums[i] = scan.nextInt();
count[i] = nums[i];
}
// 个数组排一下序方便找到较中间的那个数
Arrays.sort(count);
// 找到中间的索引
int index = 0;
// 分情况讨论值
if (n % 2 == 0) {
index = n / 2 + 1;
} else {
index = n / 2;
}
// 找到中间值
int middle = count[index];
for (int i = 0; i < n; i++) {
// 判断得到最终结果
if (nums[i] < middle) {
System.out.print(middle - nums[i] + 1);
System.out.print(" ");
} else {
System.out.print(0);
System.out.print(" ");
}
}
}
试题 E: 求阶乘
时间限制: 1.0s 内存限制: 512.0MB
本题总分:15 分
【问题描述】
满足 N! 的末尾恰好有 K 个 0 的最小的 N 是多少?
如果这样的 N 不存在输出 −1。
【输入格式】
一个整数 K。
【输出格式】
一个整数代表答案。
【样例输入】
2
【样例输出】
10
【评测用例规模与约定】
对于 30% 的数据,1 ≤ K ≤ .
对于 100% 的数据,1 ≤ K ≤ .
思路与题解:
本题要解决两个问题,1.整型数长度越界 2.直接遍历搜索的时间复杂度很大,不可能实现
所以要对判断条件作预处理,避免以上两个问题:
如果末尾存在'0'就是要凑10,而只有2和5两个因数才能得到10,又因为阶乘中2的个数远远大于5,所以要凑5,
注意对于25,125等数字其中包含不止一个5,所以不能直接输出5K,当k为5时,25的阶乘末尾有6个0,暴力求解: 后面以0结尾的一定是5!....(5的倍数的阶乘) 所以只需要判断5的倍数的阶乘 (判断的数)/5 就是含有5的个数 也是阶乘后0的个数。分析如下:
public static void Java_B_E() {
Scanner sc = new Scanner(System.in);
long k = sc.nextLong();
long count; // 含有5的个数 也是阶乘后0的个数
long a = 5; // 直接从5的阶乘(120)开始判断
while (true) {
long tempA = a;
count = 0;
while (tempA > 0) {
tempA /= 5;
count += tempA;
}
if (count < k) {
a += 5;
} else if (count == k) {
System.out.println(a);
break;
} else {
System.out.println(-1);
break;
}
}
}
试题 F: 最大子矩阵
时间限制 : 1.0s内存限制 : 512.0MB本题总分: 15 分【问题描述】小明有一个大小为 N × M 的矩阵,可以理解为一个 N 行 M 列的二维数组。我们定义一个矩阵 m 的稳定度 f ( m ) 为 f ( m ) = max ( m ) − min ( m ) ,其中 max ( m )表示矩阵 m 中的最大值, min ( m ) 表示矩阵 m 中的最小值。现在小明想要从这个矩阵中找到一个稳定度不大于 limit 的子矩阵,同时他还希望这个子矩阵的面积越大越好(面积可以理解为矩阵中元素个数)。子矩阵定义如下:从原矩阵中选择一组连续的行和一组连续的列,这些行列交点上的元素组成的矩阵即为一个子矩阵。【输入格式】第一行输入两个整数 N , M ,表示矩阵的大小。接下来 N 行,每行输入 M 个整数,表示这个矩阵。最后一行输入一个整数 limit ,表示限制。【输出格式】输出一个整数,分别表示小明选择的子矩阵的最大面积。【样例输入】3 42 0 7 90 6 9 78 4 6 48【样例输出】6【样例说明】满足稳定度不大于 8 的且面积最大的子矩阵总共有三个,他们的面积都是6 (粗体表示子矩阵元素):2 0 7 90 6 9 78 4 6 42 0 7 90 6 9 78 4 6 42 0 7 90 6 9 78 4 6 4【评测用例规模与约定】评测用例编号 N M1, 2 1 ≤ N ≤ 10 1 ≤ M ≤ 103, 4 N = 1 M ≤ 1000005 ∼ 12 1 ≤ N ≤ 10 M ≤ 1000013 ∼ 20 1 ≤ N ≤ 80 1 ≤ M ≤ 80对于所有评测用例, 0 ≤ 矩阵元素值 , limit ≤ 。
思路与题解:
时间有限,直接暴力枚举。
static int[][] arr;
public static void Java_B_F() {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int M = scanner.nextInt();
arr = new int[N][M];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
arr[i][j] = scanner.nextInt();
}
}
int limit = scanner.nextInt();
int max_area = Integer.MIN_VALUE;
for (int i = N; i > 0; i--) {
for (int j = M; j > 0; j--) { // i*j的矩阵
for (int x = 0; x <= N - i; x++) {
for (int y = 0; y <= M - j; y++) { // 左上角坐标
int max = find_max(i, j, x, y);
int min = find_min(i, j, x, y);
if ((max - min) <= limit) {
max_area = Math.max(max_area, i * j);
}
}
}
}
}
System.out.println(max_area);
}
private static int find_min(int i, int j, int x, int y) {
// 寻找最小值
int res = Integer.MAX_VALUE;
for (int n = x; n < x + i; n++) {
for (int m = y; m < y + j; m++) {
res = Math.min(res, arr[n][m]);
}
}
return res;
}
private static int find_max(int i, int j, int x, int y) {
// 寻找最大值
int res = Integer.MIN_VALUE;
for (int n = x; n < x + i; n++) {
for (int m = y; m < y + j; m++) {
res = Math.max(res, arr[n][m]);
}
}
return res;
}
以上是A~F前6道题的真题解析,真题解析及内容排版不容易,如果对各位有帮助的话,那就快赞起来吧,感谢关注、收藏、一键三连!
下一篇文章链接:2022年第十三届蓝桥杯Java B组(第二部分 G~J题)