程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

java(0)

标签  

暂无标签

日期归档  

2023-06(2)

蓝桥杯第十二届真题解析

发布于2022-04-14 19:12     阅读(633)     评论(0)     点赞(21)     收藏(4)


目录

前言

考试技巧

真题解析        

第一题 (ASC)

第二题 (卡片)

第三题 (直线)

第四题 (货物摆放)

第五题 (路径)

第六题 (时间显示)

第七题 (最少砝码)

第八题 (杨辉三角形)

第九题 (双向排序)

第十题 (括号序列)

总结


前言

        蓝桥杯第十三届省赛在4月9号开始,按照以往惯例,基本填空题4道,编程题2-3道,省一基本就稳了。

        蓝桥杯省赛考的比较基础,除了最后一题,其他基本都是简单或者中等题,我们不需要所有题都做出来,只需要保证自己会做的不错,那么省一基本没有什么问题。下面是我上一次参加省赛的奖状


考试技巧

        根据我自己参加比赛的经历,省赛整体难度较低,大部分题目都可以暴力得部分分数,对于省赛,我们需要重点复习以下知识点

  1. 对于java组,我们必须要能够熟练掌握BigInteger,BigDecimal这2个类必须掌握,如果不会,马上去学习,这2个类可以实现大数的运算,具有奇效!!!
  2. 在省赛中,基本每次都有关于时间的题目,所以,对于时间的api,我们也必须要能够掌握,在java中,例如Data类,Calendar,LocalDate,LocalDateTime这几个类也必须掌握。
  3. 在省赛中数据结构肯定会考,基本的DFS,BFS必须要会,树的遍历,特点也要熟悉,对于图的几种基本算法也要学一下,如最短路径
  4. 上面的3点是必须掌握的,下面就是提升类的,蓝桥杯在以前一直被称为暴力杯,这是因为在前几届的蓝桥杯确实都是暴力解题,但是现在开始提升难度了,在上一届dp(动态规划)的题就开始增多了,如果想拿个好成绩,别犹豫,马上去刷动态规划的题目吧!!
  5. 接下来就是字符串相关的,这个也考的十分的多,建议去leetcode看一下字符串专栏,大致了解下常见的算法,在比赛时遇到最起码有个方向
  6. 下一点,全排列,不知道大家会不会,由于java没有现成的函数,所以建议现在自己写下函数,这个用到的几率很大
  7. 这点很重要,认真读题,认真读题,认真读题,题目建议多读几遍,彻底弄清楚意思后再开始想解题思路
  8. 对于难题,10分钟没有思路,马上跳过,先把自己能做的全部做了再思考,蓝桥杯的难度一般都是随题目号数递增的,也就是越到后面越难
  9. 做题,如果不是特别有经验,建议第一种解法都从暴力开始,然后进行优化
  10. 最后一点,蓝桥杯的测试案列特别少,你写完代码后可能觉得自己做对了,测试用例也对,然后就直接提交了,比赛结束后才发现自己没有考虑周全,这时已经为时已晚,我们在写完代码后,建议至少编写5个测试用例及以上,对代码进行测试,并且测试用例要数值比较大或者比较刁钻。

        总之,蓝桥杯省赛难度不大,只要学过基本的数据结构和算法,省一基本没问题,省赛的差距就是细心,最后再重复三次,细心,细心,细心


真题解析        

        下面对上一届的题目进行讲解说明,也就是第十二届java B组


第一题 (ASC)

        这道题送分题,不解释,直接给出答案,76


第二题 (卡片)

         这道题就是暴力模拟,我们定义10大小的数组代表0-9,每个值都是2021,然后循环判断,如果数组值都不为0,那么就继续。我们对循环的数字依次得到每个位数,然后再数组中进行相减就行,可能描述有点模糊,下面直接看代码。

  1. import java.util.Arrays;
  2. public class Main {
  3. public static void main(String[] args) {
  4. int[] nums = new int[10];
  5. Arrays.fill(nums, 2021);
  6. int ans = 1;
  7. //设置标记,是否退出循环
  8. boolean flag = false;
  9. while (true) {
  10. //对于每一个num,通过字符串方式获取每一个数字
  11. for (char num : (ans + "").toCharArray()) {
  12. //将对于位置的数字-1,看是否为0
  13. if (--nums[num - '0'] == 0) {
  14. flag = true;
  15. break;
  16. }
  17. }
  18. if (flag) break;
  19. ans++;
  20. }
  21. System.out.println(ans);
  22. }
  23. }

        答案为:3181


第三题 (直线)

        这道题也简单,需要注意的就是浮点数的问题。y=kx+b,思路就是算出所有的直线的斜率k和b,然后放入set去重就行,这里需要重点注意精度问题,注意浮点数误差,我是直接使用java的BigDecimal解决的

  1. import java.math.BigDecimal;
  2. import java.math.RoundingMode;
  3. import java.util.HashSet;
  4. public class Main {
  5. public static void main(String[] args) {
  6. HashSet<String> hashSet = new HashSet<>();
  7. for (int i = 0; i < 20; i++) {
  8. for (int j = 0; j < 21; j++) {
  9. for (int m = i + 1; m < 20; m++) {
  10. for (int n = 0; n < 21; n++) {
  11. // y = kx + b通过2个点算出 b和k,然后返回b_k字符串,存入set
  12. String bk = getBK(i, j, m, n);
  13. hashSet.add(bk);
  14. }
  15. }
  16. }
  17. }
  18. //这里加20是因为有20条直线没有斜率
  19. System.out.println(hashSet.size() + 20);
  20. }
  21. public static String getBK(double x1, double y1, double x2, double y2) {
  22. // k保留小数点后50位
  23. BigDecimal k = new BigDecimal(y1 - y2).divide(new BigDecimal(x1 - x2), 50, RoundingMode.FLOOR);
  24. BigDecimal b = new BigDecimal(y1).subtract(new BigDecimal(x1).multiply(k));
  25. // b和k都保留15位小数
  26. b = b.setScale(15, RoundingMode.FLOOR);
  27. k = k.setScale(15, RoundingMode.FLOOR);
  28. return b + "_" + k;
  29. }
  30. }

        答案为:40257


第四题 (货物摆放)

        这道题直接暴力解决即可,没什么难度,算出n的所有因数,然后循环判断就行

  1. import java.util.HashSet;
  2. public class Main {
  3. public static void main(String[] args) {
  4. long num = 2021041820210418L;
  5. HashSet<Long> hashSet = new HashSet<>();
  6. //将num所有因数加入集合
  7. for (long i = 1; i <= Math.sqrt(num); i++) {
  8. if (num % i == 0){
  9. hashSet.add(i);
  10. hashSet.add(num / i);
  11. }
  12. }
  13. long ans = 0;
  14. //暴力对所有因数进行循环
  15. for (Long x : hashSet) {
  16. for (Long y : hashSet) {
  17. for (Long z : hashSet) {
  18. if (x * y * z == num)ans++;
  19. }
  20. }
  21. }
  22. System.out.println(ans);
  23. }
  24. }

         答案:2430


第五题 (路径)

        这道题就是想考察图里面的最短路径问题,但是我们可以转化为dp来做,首先求出所有点到后面21个的距离,存入数组,然后进行dp即可,dp[i] = min(dp[i],dp[i-k][k]) k范围就是1-21 

  1. public class Main {
  2. public static void main(String[] args) {
  3. long[] dp = new long[2022];
  4. //存放当前点到后面21个点的距离,下标1开始
  5. long[][] dis = new long[2022][22];
  6. for (int i = 1; i < 2022; i++) {
  7. for (int j = 1; j < 22; j++) {
  8. if (i + j > 2021) break;
  9. dis[i][j] = getDis(i, i + j);
  10. }
  11. }
  12. for (int i = 1; i < 2022; i++) {
  13. long min = Long.MAX_VALUE;
  14. //求出到当前点的最小值
  15. for (int j = 1; j <= 21; j++) {
  16. if (i - j <= 0) break;
  17. min = Math.min(min, dp[i - j] + dis[i - j][j]);
  18. }
  19. if (min != Long.MAX_VALUE) dp[i] = min;
  20. }
  21. System.out.println(dp[dp.length - 1]);
  22. }
  23. public static long getDis(long a, long b) {
  24. return a * b / gcd(a, b);
  25. }
  26. public static long gcd(long a, long b) {
  27. return a % b == 0 ? b : gcd(b, a % b);
  28. }
  29. }

        答案:10266837


第六题 (时间显示)

        送分题,不解释,直接给出代码,注意输出格式,建议使用printf

  1. import java.util.Scanner;
  2. public class Main {
  3. public static void main(String[] args) {
  4. long time = new Scanner(System.in).nextLong();
  5. long h = (time / 1000 / 60 / 60) % 24;
  6. long m = (time / 1000 / 60) % 60;
  7. long s = (time / 1000) % 60;
  8. System.out.printf("%02d:%02d:%02d", h, m, s);
  9. }
  10. }

第七题 (最少砝码)

         这道题怎么说呢,可以动态规划,可以暴力模拟,但是最优解法是平衡3进制模拟,不知道大家听说过3进制没有,这里使用3进制来做,砝码3种状态刚好对应,放左边,放右边,不放,原理就是3进制,两两组合,-1,0,1,组合后可以表示不重复的9个数

三进制十进制
-1-1
00
11
-1 -1-4
-1 0-3
-1 1-2
1 -12
1 03
1 14

     三进制数可以表示所有    [-\frac{3^n-1}{2},\frac{3^n-1}{2}](n\in Z)的数,又因为题目需要满足条件为\frac{3^n-1}{2}\geq N,通过计算,可以求出n≥log3​(2N+1),所以我们需要的砝码重量就是3^{x},x>=0,下面就可以很容易的写代码了,我说的可能不是很清楚,可以看下下面的解释,如果不理解,直接跳过也没关系,暴力,dp都能得大部分分。

  1. 举个例子,平衡3进制的1和3,也就是 1 和 10这2个数就可以表示到11,也就是可以表示到4
  2. 十进制1,3,9,平衡三进制表示为 1 10 100,
  3. 这3个数通过加减运算就可以表示到-1-1-1到111的所有范围,也就是 (-14,14)
  4. 十进制1,3,9,27,平衡三进制表示为 1 10 100 1000,
  5. 这4个数就可以表示 -1-1-1-1到1111的所有范围也就是(-40,40)

        如果还不明白,可以参考 对称三进制数详解 

  1. import java.util.Scanner;
  2. public class Main {
  3. public static void main(String[] args) {
  4. long n = new Scanner(System.in).nextLong();
  5. int count = 1;
  6. int i;
  7. for (i = 1; count < n; i++) {
  8. count += Math.pow(3, i);
  9. }
  10. System.out.println(i);
  11. }
  12. }

第八题 (杨辉三角形)

         这道题涉及到数学推导,下面给出2种解放,第一种暴力,可以得一半的分

  1. import java.util.Scanner;
  2. public class Main {
  3. public static void main(String[] args) {
  4. int n = new Scanner(System.in).nextInt();
  5. if (n == 1) {
  6. System.out.println(1);
  7. return;
  8. }
  9. //动态dp,2行进行切换
  10. int[][] dp = new int[2][100000];
  11. long count = 1;
  12. dp[0][1] = 1;
  13. int i = 1, j = 1;
  14. //当前层数
  15. for (int layer = 2; ; layer++) {
  16. //每层的数量和当前层数相同
  17. for (int k = 0; k < layer; k++) {
  18. //简单dp
  19. if (layer % 2 == 0) dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1];
  20. else dp[i][j] = dp[i + 1][j] + dp[i + 1][j - 1];
  21. count++;
  22. if (dp[i][j++] == n) {
  23. System.out.println(count);
  24. return;
  25. }
  26. }
  27. //根据层数判断是从0开始还是1开始
  28. i = layer % 2 != 0 ? 1 : 0;
  29. j = 1;
  30. }
  31. }
  32. }

         如果想要得全部分,那么就要进行数学推导,从数学的方面来考虑,由于过程比较复杂,篇幅有限,直接给出推导的链接,很详细,可以自己进行查看 数学推导 得分为100


第九题 (双向排序)

         这道题也是用到数学,但是我们暴力解决可以获得60分,也还行,下面给出暴力解法的代码和数学推导的链接

  1. import java.util.Arrays;
  2. import java.util.Scanner;
  3. public class Main {
  4. public static void main(String[] args) {
  5. Scanner scanner = new Scanner(System.in);
  6. int n = scanner.nextInt();
  7. int m = scanner.nextInt();
  8. Integer[] arr = new Integer[n+1];
  9. for (int i = 1; i < arr.length; i++) {
  10. arr[i] = i;
  11. }
  12. for (int i = 0; i < m; i++) {
  13. int num1 = scanner.nextInt();
  14. int num2 = scanner.nextInt();
  15. //直接调用api
  16. if (num1 == 0){
  17. Arrays.sort(arr, 1, num2+1, (o1, o2) -> o2-o1);
  18. }else {
  19. Arrays.sort(arr, num2, n+1);
  20. }
  21. }
  22. for (int i = 1; i <= n; i++) {
  23. System.out.print(arr[i]+" ");
  24. }
  25. }
  26. }

         由于博客已经很长了,数学推导不做结束,给出链接自行查看即可 数学推导,这个就可以得到100分


第十题 (括号序列)

         最后一题很难,一般都是留给打 ACM 的做的,如果不是打acm的直接跳过,对成绩没有任何影响,这道题就不进行解释了,如果感兴趣,参考 括号序列详解,这位大佬给出了详细的解法,可以参考一下


总结

        蓝桥杯难度主要集中在后面几题,最后一题直接放弃,我们如果没有思路,那么就使用暴力即可,能得多少分算多少,大家要相信,你觉得难,其他人也觉得难,蓝桥杯省赛,填空题4道,编程题3道,省一肯定没问题。

        最后再说一点,省赛不难,最重要的就是认真读题,认真读题,认真读题,细心,细心,再细心。祝愿大家都能在蓝桥杯中取得好成绩!!!

原文链接:https://blog.csdn.net/m0_51545690/article/details/123979651



所属网站分类: 技术文章 > 博客

作者:java王侯

链接:http://www.javaheidong.com/blog/article/412767/8167885f02aeb222b2b6/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

21 0
收藏该文
已收藏

评论内容:(最多支持255个字符)