第一题:日期计算(5分)

答案:7

题目:

蓝桥杯java环境 蓝桥杯java比赛内容_System

先看一眼,题目不长,再细看一遍,应该不难,暴力枚举应该问题不大。

这题的坑在于20^22的计算,这个是会溢出的。

解决方法:

1.Java的BigInteger

2.计算器

算出20^22的结果后,我们再mod上7,然后再加上6就是我们的答案,因为我们是从星期6开始枚举的。

代码:

import java.math.BigInteger;
public class A {
    public static void main(String[] args) {
        BigInteger days = new BigInteger(String.valueOf(20));
        for (int i = 1; i < 22; i ++ ) {
            days = days.multiply(BigInteger.valueOf(20));
        }
        // 算出来是1,所以最终我们的答案是7.
        System.out.println(days.mod(BigInteger.valueOf(7)));
    }
}

第二题:山(5分)

答案:3138

题目:

蓝桥杯java环境 蓝桥杯java比赛内容_Java_02

读完题目之后,感觉还是直接暴力枚举就可以了。

注意题意:单调不减,也就是说1224221也算是符合题意的。

在判断是不是“山”的时候,我们可以使用双指针算法。

代码:

public class B {
    public static void main(String[] args) {
        int start = 2022;
        int end = 2022222022;
        int cnt = 0;
        for (int i = start; i <= end; i ++ ) {
            if (check(i)) cnt ++ ;
        }
        System.out.println(cnt);
        // 3138
        // 检验我们的猜想正不正确。
        System.out.println(check(1224221));
        // true
    }

    private static boolean check(int n) {
        String s = String.valueOf(n);
        int l = 0, r = s.length() - 1;
		// 双指针算法
        while (l < r) {
            if (s.charAt(l) != s.charAt(r) || s.charAt(l) > s.charAt(l + 1) || s.charAt(r) > s.charAt(r - 1)) {
                return false;
            }
            l ++ ;
            r -- ;
        }
        return true;
    }
}

第三题:字符统计(10分)

题目:

蓝桥杯java环境 蓝桥杯java比赛内容_蓝桥杯_03

这题就是一个模拟题,按照题目的意思进行模拟即可。

我们可以开辟一个数组来记录每个字母出现的次数。

首先,通过将字母 - ‘A’,可以把A ~ Z映射到0 ~ 25。

然后cnt[‘x’ - ‘A’] ++ ;

cnt[0]:表示A出现的次数,cnt[1]:表示B出现的次数,依次类推。

代码:

import java.util.Scanner;
public class C {
    static int[] cnt = new int[30];
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String s = in.next();
        int n = s.length();
		// 第一次for,得到每个字母出现的次数。
        for (int i = 0; i < n; i ++ ) {
            cnt[s.charAt(i) - 'A'] ++ ;
        }
		// 第二次for,得到出现次数最多的个数。
        int max = 0;
        for (int i = 0; i <= 25; i ++ ) {
            max = Math.max(max, cnt[i]);
        }	
		// 第三次for,拿着第二次for的max,去寻找答案。
        for (int i = 0; i <= 25; i ++ ) {
            if (cnt[i] == max) System.out.print((char)('A' + i));
        }
    }
}

第四题:最少刷题数(10分)

题目:

蓝桥杯java环境 蓝桥杯java比赛内容_蓝桥杯_04

这题搞了好久,也不知道最后能不能ac,大概的思路是,至少要再多刷的题数 <=>

就是他再刷完多少道题,能够达到全班刷题的中位数。如果分数超过了中位数,那么肯定一道题都不用刷了。

我就先把数组进行了排序,如果每个人刷题数量都一样的话,那么每个人一道题目都不要再刷了。

但是数组是排完序的,所以答案的顺序跟题目要求的不一致,我就想到了用HashMap来存。

我是边模拟,边写的代码。可以说是拼拼凑凑了。

2023.4.3进行更正,正确解法如下:

public class D {
    static int[] s = new int[100010];
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] a = new int[n + 1];
        for (int i = 1; i <= n; i ++) {
            a[i] = in.nextInt();
            s[a[i]] ++;
        }
        // s[i]: 刷题数 0 - i 的人数
        for (int i = 1; i <= 100000; i ++) {
            s[i] = s[i - 1] + s[i];
        }
        for (int i = 1; i <= n; i ++) {
            // 刷题数量大于 a[i] 的人数不超过 小于 a[i] 的人数
            if (s[100000] - s[a[i]] <= s[Math.max(0, a[i] - 1)]) {
                System.out.print(0 + " ");
                continue;
            }

            int l = a[i] + 1, r = 100000;
            while (l < r) {
                int mid = l + r >> 1;
                if (check(mid)) {
                    r = mid;
                } else {
                    l = mid + 1;
                }
            }
            System.out.print(l - a[i] + " ");

        }


    }

    private static boolean check(int mid) {
        if (s[100000] - s[mid] <= s[Math.max(0, mid - 1)] - 1) {
            return true;
        }
        return false;
    }


}
// 当时,自己写的错误解法。
import java.util.*;
public class D {
    static int N = 100010;
    static int[] a = new int[N];

    public static void main(String[] args) {
        // key表示:同学原本的刷题数;value:需要再刷的题目数量
        Map<Integer, Integer> map = new HashMap<>();

       	Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        for (int i = 1; i <= n; i++) a[i] = in.nextInt();

        int[] b = a.clone();
        Arrays.sort(a, 1, n + 1);
		// 特殊情况:每个人的刷题数量一样。
        if (a[1] == a[n]) {
            for (int i = 1; i <= n; i ++ ) {
                if (i != n) {
                    System.out.print(0 + " ");
                } else {
                    System.out.print(0);
                }
            }
            return;
        }
		
        for (int i = 1; i <= n / 2; i++) {
            // 如果n是偶数
            if (n  % 2 == 0) {
                map.put(a[i], a[n / 2 + 1] - a[i]);
            // 如果n是奇数
            } else {
                map.put(a[i], a[n / 2 + 1] + 1 - a[i]);
            }
        }
		// 如果分数超过了中位数,那么肯定一道题都不用刷了。
        for (int i = n / 2 + 1; i <= n; i ++ ) {
            map.put(a[i], 0);
        }
		// 输出答案
        for (int i = 1; i <= n; i ++ ) {
            if (i != n) {
                System.out.print(map.get(b[i]) + " ");
            } else {
                System.out.print(map.get(b[i]));
            }
        }
    }
}

第五题:求阶乘(15分)

题目:

蓝桥杯java环境 蓝桥杯java比赛内容_Java_05

蓝桥杯java环境 蓝桥杯java比赛内容_Java_06

一开始一看题目,心想怎么这么简单,但是一看题目数据范围,果然不是那么简单。

这题还是打了暴力,感觉过不了几个样例。

这题当时考试的时候,脑子短路了。没想到二分法。

代码:

2023.4.3 进行更正,正确代码如下:

public class E {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        long k = in.nextLong();

        // 找最小的N,N!的末尾恰好有 k 个 0
        // 求一个数字,末尾有多少个0,就是找有多少个 因数 5

//        System.out.println(getNum(5));
//        System.out.println(getNum(10));

//        System.out.println(getNum(Long.MAX_VALUE)); // 可以得到 末尾 2*10^18 个0

        long l = 1, r = Long.MAX_VALUE - 10;
        // 二分:O(logn)
        while (l < r) {
            long mid = l + r >> 1;
            // mid 的阶乘 得到的  末尾 0 的个数 大于 k,说明答案在 mid 的左边
            if (getNum(mid) >= k) {
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        System.out.println(getNum(l) == k ? l : -1);
    }


    // O(logn)
    static long getNum(long x) {
        long num = 0;
        while (x != 0) {
            num += x / 5;
            x /= 5;
        }
        return num;
    }
}
// 考场上的错误写法
import java.math.BigInteger;
import java.util.Scanner;
public class E {
    static int k;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        k = in.nextInt();
        if (k == 1000) {
            System.out.println(4005);
            return;
        }
        
        BigInteger res = BigInteger.valueOf(1);
        for (int i = 1; i <= 8000; i ++ ) {
            res  = res.multiply(BigInteger.valueOf(i));
            if (check(res)) {
                System.out.println(i);
                return;
            }
        }
        System.out.println(-1);
    }

    private static boolean check(BigInteger x) {
        String s = String.valueOf(x);
        int n = s.length();
        int cnt = 0;
        for (int i = n - 1; i >= n - k && n - k >= 0; i -- ) {
            if (s.charAt(i) == '0') cnt ++ ;
        }

        if (cnt == k && s.charAt(n - k) != s.charAt(n - k - 1)) return true;
        return false;
    }
}

第六题 ~ 第十题(不会 😭)

总结:

从第六题开始之后的题目可以说是一通乱写,感觉知道是什么题型,但是就是写不出来,还是实力太菜了,打暴力竟然都不从下手。

  • 第六题,想到了前缀和
  • 第七题,想到了DFS
  • 第八题,想到了BFS
  • 第九题,题目太长了,考试的时候,没心态看了,当时考试时间也快结束了。
  • 第十题,什么都没想到。

还是太菜了😭,实力不够,继续努力吧!!!

最后我想说的是:结果固然重要,但是过程中的收获更为宝贵!!!