第十三届蓝桥杯省赛JavaB组真题(Java题解解析)
创始人
2024-06-02 13:38:41
0

文章目录

  • 前言
  • 试题A:星期计算(5分)
    • 题目
    • 题解
      • 解法1:步骤取余计算(int即可)
      • 解法2:使用API
  • 试题B:山(5分)
    • 题目
    • 题解
      • 解法1:暴力
  • 试题C:字符统计(10分)
    • 题目
    • 题解(哈希)
  • 试题D:最少刷题数(10分)
    • 题目
    • 题解
      • 解法1:排序(过7个点)
  • 试题E:求阶乘(15分)
    • 题目
    • 题解
      • 解法1:算数基本定理+枚举(过5个点)
      • 解法2:二分+算数基本定理
  • 试题F:最大子矩阵(15分)
    • 题目
    • 题解
      • 解法1:暴力(过10%数据)
      • 解法2:单调队列(学习中)
  • 试题G:数组切分(20分)
    • 题目
    • 题解
      • 解法1:暴力枚举(过5个点)
      • 解法2:DP
  • 试题H:回忆迷宫(20分)
    • 题目
    • 题解
  • 试题J:拉箱子(25分)
    • 题目
    • 题解

前言

总共150分

初次解题过程:

A:+0分(答案算错了(计算得6,最终答案为7),想到是采用步骤做取余计算,但是没有使用多个样例来进行测试,就直接取答案了。)
B:+0分(答案算错了(计算得644,最终答案为3138)),我裂开,题意看错了,前一半是进行升序(实际上可以<=,我看成是只能<),实际上我们只需要对每一个字符判断前面一半是升序 && 是回文即可解决。(60秒)
C:+10分
D:+1(10个案例点就过了1个)
E:+0(本来认为是找规律题,没想到考的是算数基本定理)
F:+1.5(写了个暴力,优化需要使用优先队列 使用空间换时间)
G:+10(写了递归搜索就过了5个用例,优化使用DP)
I:
J:

第十三届蓝桥杯省赛JavaB组真题

试题A:星期计算(5分)

题目

image-20230311155421104

题解

答案:7

解法1:步骤取余计算(int即可)

public class Main {public static void main(String[] args) {int temp = 20;// 循环22次for (int i = 1; i <= 21; i++) {temp = (temp * 20) % 7;}// 打印最终结果// 其中(5 + temp) % 7是计算得到目标星期x的x下标(从0开始的),所以最后要进行+1。System.out.println((5 + temp) % 7 + 1);}
}

解法2:使用API

①直接使用Math.pow

public class Main {public static void main(String[] args) {System.out.println(Math.pow(20, 22) % 7 + 6);}
}

②使用BigInteger

import java.math.BigInteger;public class Main {public static void main(String[] args) {BigInteger bg = new BigInteger("20");//pow取次方数,remainder进行取余bg = bg.pow(22).remainder(BigInteger.valueOf(7)).add(BigInteger.valueOf(6));System.out.println(bg);}
}

image-20230311161038958


试题B:山(5分)

题目

image-20230311170747956

题解

本题由于是填空题,可以直接写暴力来计算答案。

暴力法:枚举[2022, 2022222022],进行check山型递增递减情况以及回文。

解法1:暴力

非调用API版本:

public class Main {public static boolean huiwen(int num) {char[] chs = String.valueOf(num).toCharArray();for (int l = 0, r = chs.length - 1; l <= r; l++, r--) {if (chs[l] != chs[r])return false;}return true;}public static boolean islianxu(int num) {char[] chs = String.valueOf(num).toCharArray();int n = chs.length;int b1 = n % 2 == 1 ? n / 2 : n / 2 - 1;int b2 = n / 2;// [0, b1] 单调增for (int i = 1; i <= b1; i++) {if (chs[i] <= chs[i - 1])return false;}// [b2, n - 1]单调减for (int i = b2 + 1; i < n; i++) {if (chs[i] >= chs[i - 1])return false;}return true;}public static void main(String[] args) {long start = System.currentTimeMillis();int ans = 0;for (int i = 2022; i <= 2022222022; i++) {if (islianxu(i) && huiwen(i)) {ans++;}}System.out.println(ans);long end = System.currentTimeMillis();System.out.println("" + ((double) (end - start) / 1000) + "秒");}
}  

image-20230311170421343

调用API版本:

public class Main {// 只需要比较前半部分public static boolean islianxu(int num) {char[] arr = String.valueOf(num).toCharArray();int n = arr.length;int len = n % 2 == 0 ? n / 2 - 1 : n / 2;// 比较前半部分for (int i = 1; i <= len; i++) {if (arr[i] < arr[i - 1])return false;}return true;}// 反转字符串来进行比较(判断是否是回文)public static boolean huiwen(int num) {String targetStr = (new StringBuilder(num + "")).reverse().toString();return String.valueOf(num).equals(targetStr);}public static void main(String[] args) {long start = System.currentTimeMillis();int ans = 0;for (int i = 2022; i <= 2022222022; i++) {if (islianxu(i) && huiwen(i)) {ans++;}}System.out.println(ans);long end = System.currentTimeMillis();System.out.println("" + ((double) (end - start) / 1000) + "秒");}
}

image-20230311170137375

试题C:字符统计(10分)

题目

蓝桥杯官网题-字符统计

image-20230311171142894

题解(哈希)

哈希走一遍。

import java.io.BufferedReader;
import java.io.InputStreamReader;public class Main {static final BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));public static void main(String[] args) throws Exception {int[] cnts = new int[26];String str = cin.readLine();char[] chs = str.toCharArray();int max = 0;for (char ch : chs) {cnts[ch - 'A']++;max = Math.max(cnts[ch - 'A'], max);}for (int i = 0; i < 26; i++) {if (cnts[i] == max) {System.out.printf("%c", (char) (i + 'A'));}}}
}

本地调试:

image-20230303174858319

蓝桥杯官网提交:

image-20230311163327737


试题D:最少刷题数(10分)

题目

蓝桥杯官网题-最少刷题数

image-20230311171540816

image-20230311171548836

题解

题目要求:刷题比他多的学生人数不超过刷题比他少的人数。多的 <= 少的。

解法1:暴力(排序),时间复杂度都是在排序上,确定n个小朋友多做的时间复杂度是O(n)。

思路:
1、对所有小朋友做的题数进行排序
2、确定一个中间值target,分别使用两个计数变量(l、r)记录>target与=target那么即可直接输出0,若是

解法1:排序(过7个点)

复杂度分析:时间复杂度O(n.logn);空间复杂度O(n)

import java.util.*;
import java.io.*;
// 1:无需package
// 2: 类名必须Main, 不可修改public class Main {static final BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));static final PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));static final int N = 100010;static int[] a = new int [N];static int n;public static void main(String[] args) throws Exception{n = Integer.parseInt(cin.readLine());String[] ss = cin.readLine().split(" ");for (int i = 0; i < n; i ++) {a[i] = Integer.parseInt(ss[i]);}//克隆,来进行排序int[] temp = a.clone();Arrays.sort(temp, 0, n);//target:目标值,l:比target小的数量,r:比target大的数量int target = temp[n / 2], l = 0, r = 0;for (int i = 0; i < n; i ++) {if (temp[i] > target) {r ++;}else if (temp[i] < target) {l ++;}}//由于我们本身就是取的排序中间值,若是大于中间值的数量  >  小于中间值的数量//那么我们的目标值就需要进行+1if (l < r) target ++;//接着来进行输出结果for (int i = 0; i < n; i ++) {if (a[i] >= target) {out.printf("%d ", 0);}else {//考虑到将当前值提升到target 还是 target+1(取决于左右两边>与<数的情况)//当前的值为a[i] < target,讨论关于//情况1:12778  target = 7, l = 2 r = 1, 此时a[i] = 2时,我们只需要7-2即可//情况2: 77788  target = 8(由于l < r,增加1), l = 0, r = 2, 此时a[i] = 7,为8-7即可//情况3: 11788,target = 7,l = 2, r = 2,此时a[i] = 1,我们需要将a[i]提升到target+1,才能保证r<=lout.printf("%d ", target - a[i] + (l == r ? 1 : 0));}}out.flush();}
}

image-20230311180743531


试题E:求阶乘(15分)

题目

image-20230311185331445

image-20230311185341257

题解

根据算数基本定理可以将一个数分解成若干个数的乘积。

n! = N = P1a1 P2a2 P3a3 * … Pnan,本题中需要统计的是后缀连续0的个数,那么也就是目标n!中对于10的阶乘个数,又10 = 2 * 5,想要求得目标10,那么我们就需要去匹配多对2与5,此时即为找到min(质因子2的个数,质因子5的个数),又质因子2的个数是大于5的个数,所以我们可以直接去求质因子为5的个数 == k。

对于一个数n,求得该n!中质因子为5的个数,我们只需要去对n进行不断相除即可求得。

//计算n中有多少个5
public static long check(int num) {long res = 0L;while (num > 0) {res += num / 5;num /= 5;}return res;
}

解法1:枚举1-108,每一个数表示阶乘,来去求得该阶乘的值是否是>=k,找到第一个也就是最小的n即为答案。

  • 这里枚举到108目的就是由于时间复杂度为O(n.logn),而运算次数为1亿次差不多就是1秒,所以这里取相对在临界位置的值即可。

解法2:由于去check 1-108得到的结果是递增的,那么这个枚举的过程可以修改为二分来进行搜索,此时复杂度可以直接优化为O(logn.logn),直接ac。


解法1:算数基本定理+枚举(过5个点)

复杂度分析:时间复杂度O(n.logn);空间复杂度

import java.util.*;
import java.io.*;public class Main {static final Scanner cin = new Scanner(System.in);static long N = (long)1e8;static long k;//计算n中有多少个5public static long check(int num) {long res = 0L;while (num > 0) {res += num / 5;num /= 5;}return res;}public static void main(String[] args) {k = cin.nextLong();for (int i = 1; i <= N; i ++) {//找到第一个>=k情况long res = check(i);if (res >= k) {if (res == k) System.out.println(i);else System.out.println(-1);return;}}System.out.println(-1);}
}

image-20230311202306316


解法2:二分+算数基本定理

复杂度分析:时间复杂度O(logn*logn);空间复杂度O(1)

import java.util.*;
import java.io.*;public class Main {static final Scanner cin = new Scanner(System.in);static long k;//计算n中有多少个5public static long check(long num) {long res = 0L;while (num > 0) {res += num / 5;num /= 5;}return res;}public static void main(String[] args) {k = cin.nextLong();//二分long l = 0, r = (long)9e18;while (l < r) {long mid = l + r >> 1;if (check(mid) >= k) r = mid;else l = mid + 1;}if (check(r) == k) {System.out.println(r);}else {System.out.println("-1");}}
}

image-20230311202542184


试题F:最大子矩阵(15分)

题目

image-20230311202701071

image-20230311202738271

image-20230311202750297

image-20230311202806227

题解

解法1:暴力(过10%数据)

最大数据量矩阵块数为10万

暴力法

复杂度分析:时间复杂度O(n6);空间复杂度O(n*m)

import java.io.BufferedReader;
import java.io.InputStreamReader;public class Main {static final BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));static final int N = 90, M = 100010;static int[][] a = new int[N][M];static int n, m, limit;public static void main(String[] args) throws Exception {String[] ss = cin.readLine().split(" ");n = Integer.parseInt(ss[0]);m = Integer.parseInt(ss[1]);for (int i = 1; i <= n; i++) {ss = cin.readLine().split(" ");for (int j = 1; j <= m; j++) {a[i][j] = Integer.parseInt(ss[j - 1]);}}limit = Integer.parseInt(cin.readLine());int ans = 0;// 暴力for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {// 枚举目标点for (int x = i; x <= n; x++) {for (int y = j; y <= m; y++) {// 遍历区间 起始(i, j) - (x, y)int max = 0, min = 0, s = 0;for (int xx = i; xx <= x; xx++) {for (int yy = j; yy <= y; yy++) {s++;// 数量max = Math.max(max, a[xx][yy]);min = Math.min(min, a[xx][yy]);}}if (max - min <= limit) {ans = Math.max(ans, s);}}}}}System.out.println(ans);}
}

测试:

3 4
2 0 7 9
0 6 9 7
8 4 6 4
8

image-20230306113359549

解法2:单调队列(学习中)

官方题解-学习

中间进行剪枝,中间的使用空间换时间

import java.io.BufferedReader;
import java.io.InputStreamReader;public class Main {static final BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));static final int N = 90, M = 100010;static int[][] a = new int[N][M];// 前缀和(最大值,最小值)static int[][] max = new int[N][M], min = new int[N][M];static int n, m, limit;public static void main(String[] args) throws Exception {String[] ss = cin.readLine().split(" ");n = Integer.parseInt(ss[0]);m = Integer.parseInt(ss[1]);for (int i = 1; i <= n; i++) {ss = cin.readLine().split(" ");for (int j = 1; j <= m; j++) {a[i][j] = Integer.parseInt(ss[j - 1]);int preMax = Math.max(Math.max(max[i - 1][j], max[i][j]), max[i - 1][j - 1]);max[i][j] = Math.max(preMax, a[i][j]);int preMin = Math.max(Math.max(min[i - 1][j], min[i][j]), min[i - 1][j - 1]);min[i][j] = Math.max(preMin, min[i][j]);}}limit = Integer.parseInt(cin.readLine());// 遍历整个矩阵int ans = 0;// 枚举所有行for (int i = 1; i <= n; i++) {for (int j = i; j <= n; j++) {// 左右指针for (int l = 1, r = 1, s = 0, mmax = 0, mmin = 0; r <= m; r++) {// 个数增加s += j - i + 1;// 矩阵范围最大值确定}}}}
}

试题G:数组切分(20分)

题目

image-20230311210253153

image-20230311210304718

image-20230311210317382

题解

解法1:暴力枚举(过5个点)

image-20230311135618848

暴力解法:含路径打印

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;public class Main {static final BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));static final int N = 10010;static int[] a = new int[N];static int n;static int ans;public static void dfs(int start, int step, List res) {// 若是start + step > n,越界无法判断,直接结束if (start + step > n)return;// 判断[start, start + step)区间是否是连续int max = a[start], min = a[start];for (int i = start; i < start + step; i++) {max = Math.max(a[i], max);min = Math.min(a[i], min);}// 若是当前无法构成连续区间直接结束if (step != 1 && (max - min + 1) != step) {return;}// 表示区间连续// 若是此时start+step == n,此时表示构成连续区间if (start + step == n) {ans++;System.out.println(res);return;}// 递归处理,不同的情况for (int sstep = 1; sstep <= n; sstep++) {res.add(sstep);dfs(start + step, sstep, res);res.remove(res.size() - 1);}}public static void main(String[] args) throws Exception {n = Integer.parseInt(cin.readLine());String[] ss = cin.readLine().split(" ");for (int i = 0; i < n; i++) {a[i] = Integer.parseInt(ss[i]);}// 起始步骤枚举for (int step = 1; step <= n; step++) {ArrayList res = new ArrayList<>();res.add(step);dfs(0, step, res);}System.out.println(ans);}
}

image-20230311135239670

暴力解法:不含路径打印

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;public class Main {static final BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));static final int N = 10010;static int[] a = new int[N];static int n;static int ans;public static void dfs(int start, int step) {// 若是start + step > n,越界无法判断,直接结束if (start + step > n)return;// 判断[start, start + step)区间是否是连续int max = a[start], min = a[start];for (int i = start; i < start + step; i++) {max = Math.max(a[i], max);min = Math.min(a[i], min);}// 若是当前无法构成连续区间直接结束if (step != 1 && (max - min + 1) != step) {return;}// 表示区间连续// 若是此时start+step == n,此时表示构成连续区间if (start + step == n) {ans++;return;}// 递归处理,不同的情况for (int sstep = 1; sstep <= n; sstep++) {dfs(start + step, sstep);}}public static void main(String[] args) throws Exception {n = Integer.parseInt(cin.readLine());String[] ss = cin.readLine().split(" ");for (int i = 0; i < n; i++) {a[i] = Integer.parseInt(ss[i]);}// 起始步骤枚举for (int step = 1; step <= n; step++) {ArrayList res = new ArrayList<>();res.add(step);dfs(0, step);}System.out.println(ans);}
}

image-20230311135415916


解法2:DP

数组切分(蓝桥杯题解)

import java.util.*;
import java.io.*;public class Main {static final BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));static final int N = 10010, MOD = (int)(1e9 + 7);static int[] w = new int[N];//表示以第i个为结尾,可以组成多段连续自然数的个数static int[] f = new int[N];static int n;public static void main(String[] args) throws Exception{n = Integer.parseInt(cin.readLine());String[] ss = cin.readLine().split(" ");for (int i = 1; i <= n; i ++) {w[i] = Integer.parseInt(ss[i - 1]);}//初始化f[0] = 0;for (int i = 1; i <= n; i ++) {//设置最大值,最小值int max = 0, min = Integer.MAX_VALUE;//不断的进行缩减范围 [j, j-1]、[j, j-2]、[j, j-3]作为最后一段区间//筛选[j, j-1]、[j, j-2]、[j, j-3]区间符合条件的情况,接着去叠加之前f[j - 1]已经计算好的数量for (int j = i; j > 0; j --) {max = Math.max(w[j], max);min = Math.min(w[j], min);if (max - min == i - j) f[i] = (f[i] + f[j - 1]) % MOD;}}System.out.println(f[n]);}
}

image-20230312111225237


试题H:回忆迷宫(20分)

上下左右:udrl

uuuullllddddrrrru

#试题I:红绿灯(25分)

确定思路:贪心

题目

蓝桥杯官方题解-红绿灯

题解

dp

全局最优解一定是和局部最优解有关的。


试题J:拉箱子(25分)

猜想:枚举+DP

题目

题解

相关内容

热门资讯

“倾听您的心声,服务您的需求”... 中国人民人寿保险股份有限公司(以下简称“人保寿险”)“倾听您的心声 服务您的需求”第十七届客户节于2...
佩斯科夫:俄不会对媒体有关俄乌... 转自:财联社【佩斯科夫:俄不会对媒体有关俄乌谈判报道发表评论】财联社5月18日电,据塔斯社当地时间1...
穆杰,调任新职 编辑 | 余晖山东省人民政府近日发布任免通知,山东省人民政府决定,任命穆杰为山东省煤田地质局副局长。...
融合文化、体育与生态,房山举办... 新京报讯(记者陈璐)5月18日,“登峰揽胜在房山”山地绿道徒步活动在房山区周口店镇永寿禅寺广场启幕。...
5月19日,“同”赴一场有“法... 【5月19日,“同”赴一场有“法”的旅行】锦绣河山,美好旅程。在第15个中国旅游日,人民法院新闻传媒...
探索电影+旅游的创新合作,盐城... 转自:上观新闻当120年胶片齿轮撞上Z世代的赛博心跳,一座城正用“轻舟计划”重构青年与电影的时空契约...
十位艺术大师联袂,绘就江南诗意... 转自:上观新闻艺术的笔触邂逅江南的灵韵,共赏“吴越江南”的水墨诗意。近日,位于闵行区万源路2800号...
痛惜!突发呼吸心跳骤停,他于深... 南京艺术学院5月17日发布讣告:南京艺术学院教授、博士生导师尹悟铭同志,因突发呼吸心跳骤停,经抢救无...
2024年我国卫星导航产业产值... 原标题:2024年我国卫星导航产业产值达5758亿元来源:人民日报客户端5月18日,中国卫星导航定位...
龙牙刀、结界兽、天元鼎……《哪... 新京报记者 展圣洁 编辑 白爽 校对 赵琳5月19日,年度重磅特展——“看·见殷商”展览将在北京大运...
中国铁建相关公司中标一项349... (转自:快查一企业中标了)快查APP显示,中国铁建相关公司中铁十八局集团有限公司于2025年5月15...
上海家庭医生签约数超1100万... 转自:中工网中新网上海5月18日电 (记者 陈静)家庭医生是居民健康的“第一道防线”。世界家庭医生日...
50多岁2女子无视预警爬野山被... 转自:京报网_北京日报官方网站 【#50多岁2女子无视预...
广东建工全资子公司中标一项31... (转自:快查一企业中标了)快查APP显示,广东建工相关公司广东省基础工程集团有限公司于2025年5月...
从工具到生态:金融科技的角色升... 转自:企业观察网数字金融,作为传统金融与现代信息技术深度融合的产物,正在重塑金融业务模式的底层逻辑。...
义乌至迪拜“铁海快线+中东快航... 5月18日,澎湃新闻(www.thepaper.cn)记者从中国铁路上海局集团有限公司(以下简称“上...
文化中国行|探寻国宝里的中国智... 03:12今年5月18日是第49个国际博物馆日。山西历史悠久,素有“地上文物看山西”的美誉。山西博物...
祝姜同学前程似锦!救人小伙姜昭... 来源:人民日报 【祝姜同学前程似锦!#救人小伙姜昭鹏完成...
印度南部一建筑起火,至少17人... 转自:上观新闻当地时间5月18日,印度南部特伦甘纳邦海得拉巴市一栋建筑发生火灾,目前已造成至少17人...
墨西哥海军船只撞上布鲁克林大桥... 转自:央视新闻  当地时间17日晚,一艘载有277人的墨西哥海军大型帆船在穿越美国纽约布鲁克林大桥时...