The 13th Blue Bridge Cup Provincial Competition JAVA Group B (analysis of real questions + personal experience) (question G has been updated)

Question A: Calculation of the week【Fill in the blank】

topic:

Answer: 7

Parse:

This question can directly find the remainder of 7.

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

Paste a BigInteger code

import java.math.BigInteger;
​
public class Main {
    public static void main(String[] args) {
        BigInteger bg = new BigInteger(20+"");
        BigInteger res = bg.pow(22).remainder(BigInteger.valueOf(7)).add(BigInteger.valueOf(6));
        System.out.println(res);
    }
}

Question B:【Fill in the blank】

topic:

Answer: 3138

I know that many people have misunderstood the title of this question. I know several people who only saw the palindrome, but did not see the monotonous condition. (Big brothers are busy doing the following questions)

Parse:

You can know from reading the question that palindrome numbers are left and right symmetrical, so you only need to judge whether it is a palindrome, and then judge that the number on the left is monotonically non-decreasing, and the number on the right must not increase monotonically. The number of palindrome can be judged by double pointer.

public class Main {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        int count = 0;
        for (int i = 2022; i <= 2022222022; i++) {
            if (isPalindrome(i) && check(i)) {
                count++;
            }
        }
        long end = System.currentTimeMillis();
        System.out.println(count);
        System.out.println("共用时" + (end - start) / 1000 % 60 + "秒");//测了一下时间用时40s
    }
​
    private static boolean check(int num) {
        String s = num + "";
        for (int i = 0; i < s.length() / 2; i++) {
            if (s.charAt(i) > s.charAt(i + 1)) return false;
        }
        return true;
    }
​
    private static boolean isPalindrome(int num) {
        String s = num + "";
        int n = s.length() - 1;
        for (int l = 0, r = n; l < r; l++, r --)
            if (s.charAt(l) != s.charAt(r)) return false;
        return true;
    }
}
​

Test Question C: Character Statistics [Programming Questions]

topic:

Parse:

Sign in the question and output the statistics separately.

import java.util.Scanner;
​
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        int[] arr = new int[26];
        for (int i = 0; i < s.length(); i++) {
            arr[s.charAt(i) - 'A']++;
        }
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < 26; i++) {
            max = Math.max(max, arr[i]);
        }
        for (int i = 0; i < 26; i++) {
            if(arr[i] == max) System.out.print((char) (i+'A'));
        }
    }
}

Question D: The minimum number of questions to brush [programming questions]

topic:

Parse:

I think this question is a very difficult question, but it is still quite difficult (maybe I am too good at it). The main reason is that there are many factors to consider. The core idea should be to calculate the number of numbers that are equal to the left, right and middle, and judge whether each number plus the minimum number of questions and the middle number are equal to each number. 1.

This question annoyed me at the time and wasted a lot of time. I only considered comparing it with the middle one. If it is bigger than it, I will output 0. If it is smaller than it, I will output the middle number minus num[i]+1. There is no Judging the situation where the left and right numbers are equal to the middle number, there is not all AC. Paste someone else's code here

​
import java.util.Arrays;
import java.util.Scanner;
​
public class Main {
​
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] nums = new int[n];
        int[] temp = new int[n];
        for (int i = 0; i < n; i++) {
            nums[i] = sc.nextInt();
            temp[i] = nums[i];
        }
        // 排序数组
        Arrays.sort(temp);
        // 中间的下标
        int midIndex = n / 2;
        // 中间的值
        int midValue = temp[midIndex];
​
        int midOption = 0;
​
        int option = 0;
        // 左边和中值相同值的数量
        int sameLeft = 0;
        // 右边和中值相同值的数量
        int sameRight = 0;
​
        for (int i = midIndex - 1, j = midIndex; i >= 0; i--, j++) {
            if (temp[i] == midValue) {
                sameLeft++;
            }
            if (temp[j] == midValue) {
                sameRight++;
            }
            if (temp[i] != temp[j]) {
                break;
            }
        }
​
        if (sameLeft >= sameRight) {
            option = 1;
        }
        if (sameLeft > sameRight) {
            midOption = 1;
        }
​
        for (int i = 0, len = nums.length; i < len; i++) {
            int count = 0;
            if (nums[i] == midValue) {
                count = midOption;
            } else {
                count = midValue - nums[i] + option;
                if (count < 0) {
                    count = 0;
                }
            }
            if (i != n - 1) {
                System.out.print(count + " ");
            } else {
                System.out.println(count);
            }
​
        }
    }
​
}
​

I think the method of this code is quite clever hh

-------------------------------------------------- -----------Boundary line----------------------------------- ----------------------

Updated February 7, 2023

Core idea: Sort to find the median, then count the numbers on the left and right sides that are larger and smaller than mid, and discuss them by category.

( It feels like a simulated question ) Very annoying question

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n], tmp = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
            tmp[i] = a[i];
        }
        Arrays.sort(tmp);
        int mid = tmp[n / 2];
        int bg_cnt = 0, sml_cnt = 0; // 记录比mid大的和比mid小的数
        for (int i = 0; i < n; i++)
            if (a[i] < mid) sml_cnt ++;
            else if (a[i] > mid) bg_cnt ++;

        if (bg_cnt < sml_cnt) {
            for (int i = 0; i < n; i++)
                if (a[i] < mid) System.out.print(mid - a[i] + " ");
                else System.out.print(0 + " ");
        } else if (bg_cnt == sml_cnt){
            for (int i = 0; i < n; i++)
                if (a[i] < mid) System.out.print(mid - a[i] + 1 + " ");
                else System.out.print(0 + " ");
        }else {
            for (int i = 0; i < n; i++)
                if (a[i] <= mid) System.out.print(mid - a[i] + 1 + " ");
                else System.out.print(0 + " ");
        }
    }
}

Question E: Finding the factorial

topic:

analyze

I think this question is simple again. The data range of this question is very large, so it may only be a few samples. It is also impossible to judge directly from 1 to N enumeration. The breakthrough is who multiplies who in the number and who gets 10. It is easy to think that 2*5, the number of 2 must be more than 5, so how many 0s there are in the final factorial of N depends on N How many can be divided into 5 . You can divide each number from 1 to N by 5, and then count the number of 5, because 25/5 will also get 5, so you need to use a loop to calculate.

law of violence

import java.util.Scanner;
​
public class Main {
    //后面以0 结尾的一定是5!....(5的倍数的阶乘) 所以只需要判断5的倍数的阶乘
    //(判断的数)/5 就是含有5的个数 也是阶乘后0的个数
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long k = sc.nextLong();
        long count;
        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;
            }
        }
    }
}
​

-------------------------------------------------- -----------Boundary line----------------------------------- ----------------------

Updated February 8, 2023

two points

The larger N, the more 0s at the end, which is monotonic, and the answer can be found using binary points.

import java.util.Scanner;

public class Main {
    // 找N里面有多少个5(25里有两个5) 二分出一个>=k(找大于等于k的第一个位置)的最小的N,不存在则输出-1
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long l = 1, r = Long.MAX_VALUE-5;
        long k = sc.nextLong();
        while (l < r) {
            long mid = l + r >> 1;
            if (cal(mid) >= k) r = mid;
            else l = mid + 1;
        }
        if (cal(r) == k) System.out.println(r);
        else System.out.println(-1);
    }

    private static long cal(long num) {
        long cnt = 0;
        while (num > 0) {
            cnt += num / 5;
            num /= 5;
        }
        return cnt;
    }
}

Problem F: Maximum Submatrix

topic:

Analysis: monotonic queue + dichotomous

This question feels more difficult than the G question, and the exam can only be violent....

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Scanner;
// 枚举行x1,x2,二分最大的列数len,维护滑动窗口为大小为len的最大值和最小值
// 单调队列+二分
public class Main {
    // 矩阵中最大值-最小值<=limit && 元素个数最多
    static int n, m, limit, ans;
    static int[][][] max, min;
    //max[k][i][j]代表的含义是在第k列中,第i个元素到第j个的元素最大值是多少,min数组同理。
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt(); m = sc.nextInt();
        max = new int[m + 1][n + 1][n + 1]; min = new int[m + 1][n + 1][n + 1];
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                max[j][i][i] = min[j][i][i] = sc.nextInt();
        limit = sc.nextInt();

        for (int k = 1; k <= m; k++)
            for (int i = 1; i <= n; i++)
                for (int j = i + 1; j <= n; j++) {
                    max[k][i][j] = Math.max(max[k][j][j], max[k][i][j - 1]);
                    min[k][i][j] = Math.min(min[k][j][j], min[k][i][j - 1]);
                }

        for (int x1 = 1; x1 <= n; x1++)
            for (int x2 = x1; x2 <= n; x2++) {
                int l = 1, r = m;
                while (l < r) {
                    int mid = l + r + 1 >> 1;
                    if (check(x1, x2, mid)) l = mid;
                    else r = mid - 1;
                }
                if (check(x1, x2, r)) ans = Math.max(ans, (x2 - x1 + 1) * r);
            }
        System.out.println(ans);
    }
    
    private static boolean check(int x1, int x2, int k) {
        Deque<Integer> q_min = new ArrayDeque<>();
        Deque<Integer> q_max = new ArrayDeque<>();
        // 枚举所有列
        for (int i = 1; i <= m; i++) {
            if (!q_min.isEmpty() && i - k >= q_min.peekFirst()) q_min.pollFirst();
            while (!q_min.isEmpty() && min[i][x1][x2] <= min[q_min.peekLast()][x1][x2]) q_min.pollLast();
            q_min.addLast(i);

            if (!q_max.isEmpty() && i - k >= q_max.peekFirst()) q_max.pollFirst();
            while (!q_max.isEmpty() && max[i][x1][x2] >= max[q_max.peekLast()][x1][x2]) q_max.pollLast();
            q_max.addLast(i);
            //窗口大小为k
            if (i >= k && max[q_max.peekFirst()][x1][x2] - min[q_min.peekFirst()][x1][x2] <= limit) return true;
        }
        return false;
    }
}

Test Question G: Array Segmentation

topic:

 

Parse:

Algorithm 1 Backtracking Algorithm

Enumerate all segmentation points
The backtracking algorithm can enumerate all situations. When each segmented sub-array meets the requirements of the question, the answer is ++, but the time complexity is high, and it will be tle

Tips
Q: How to judge whether the interval [i, j] can form a continuous natural number?
Answer: Only the maximum value of the interval - the minimum value of the interval == j - i (interval length)

import java.util.LinkedList;
import java.util.Scanner;

public class Main {
    static LinkedList<Integer> path =  new LinkedList<>();
    static int res = 0, mod = 1000000007;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) a[i] = sc.nextInt();
        dfs(a, 0);
        System.out.println(res % mod);
    }

    private static void dfs(int[] a, int startindex) {
        int n = a.length;
        if (startindex == n) {
            res ++;
            return;
        }
        for (int i = startindex; i < n; i++) {
            if (check(a, startindex, i)) {
                path.add(i);
                dfs(a, i + 1);
                path.removeLast();
            }
        }
    }

    private static boolean check(int[] a, int l, int r) {
        int max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;
        for (int i = l; i <= r; i++) {
            if (a[i] > max) max = a[i];
            if (a[i] < min) min = a[i];
        }
        return max - min == r - l;
    }
}

Algorithm 2 DP (positive solution)

import java.util.Scanner;

public class Main {
    static int mod = 1000000007;
    public static void main(String[] args) {
        // f[i]: 以a[i]结尾的切分合法数组的方法数量
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n + 1];
        for (int i = 1; i <= n; i++) a[i] = sc.nextInt();
        int[] f = new int[n + 1];
        f[0] = 1;
        for (int i = 1; i <= n; i++) {
            int max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;
            for (int j = i; j > 0; j--) {
                max = Math.max(max, a[j]);
                min = Math.min(min, a[j]);
                //如果a[j, i]是一段连续的自然数,那么就有以a[i]结尾的合法切分合法数量+=以a[j - 1]结尾的合法切分数量
                //即f[i] += f[j - 1]
                if (max - min == i - j)
                    f[i] = (f[i] + f[j - 1]) % mod;
            }
        }
        System.out.println(f[n]);
    }
}

Question H: Memory Maze

topic:

Parse:

Question I: Traffic lights

topic:

Parse:

Test Question J: Pulling a Box

topic:

Parse:

Guess you like

Origin blog.csdn.net/weixin_55396112/article/details/124532419