栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

第十三届蓝桥杯省赛 JAVA B组(真题解析+个人体会)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

第十三届蓝桥杯省赛 JAVA B组(真题解析+个人体会)

试题 A: 星期计算【填空题】 题目:

答案:7 解析:

这题可以直接用double来做,考的时候我还在想会不会爆精度,后来发现答案也是对的。

此题直接对7求余即可。

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

不放心的话也可以转成 BigInteger来做

贴一下BigInteger的代码

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);
    }
}
试题 B:【填空题】 题目:

 

答案:3138

这题我知道很多人把题目都给看错了,我认识好几个都是只看到了回文,没看到还有单调的条件。(大佬们都忙着做后面的题)

解析:

读题可以知道,回文数左右对称,所以只需判断是否回文,然后再判断左边的数单调不减,则右边的数一定单调不增。

可以节约一点时间,但即使这样我考试这题也跑了一分多钟hh..

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 n = num + "";
        StringBuilder sb = new StringBuilder(n);
        sb.reverse();
        for (int i = 0; i < n.length(); i++) {
            if (sb.charAt(i) != n.charAt(i)) return false;
        }
        return true;
    }
}
​

这题好像不转成字符串处理会快一点,下次再研究一下。

试题 C:字符统计【编程题】 题目:

解析:

签到题,分别统计输出即可。


import java.util.Scanner;
​
public class C {
    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'));
        }
    }
}
试题 D:最少刷题数【编程题】 题目:

 

解析:

这个题我觉得虽然是个十分题,但是还是挺难的(也可能是我太菜了)。主要是要考虑的因素比较多,核心的想法应该是要计算出左边、右边与中间相等的数的个数,分情况判断每个数加上最小刷题数与中间数相等后需不需要+1。

这题当时给我做烦了,浪费了很多时间,我只考虑了和中间的相比,比它大就输出0,比它小就输出中间的数减去num[i]+1,并没有判断左右数与中间数相等的情况,没有全部AC。这里贴一下别人的代码

​
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);
            }
​
        }
    }
​
}
​

我觉得这个代码的方法还是比较巧妙的hh

试题 E: 求阶乘 题目: 解析

这题我又给想简单了,此题的数据范围非常大,所以可能只能过极个别样例。也不能直接从1到N枚举判断,突破口是数字中谁和谁相乘得到10,很容易想到2*5,2的个数肯定比5多,所以N的阶乘最后有多少0 就看N能分成多少5 。可以从1~N每个数都除以5,然后统计个5的个数,因为25/5也会得到5,所以需要用循环计算。

这里也是贴一下大佬们的代码

暴力法

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;
            }
        }
    }
}
​

二分法

//因为k的值很大 不可能用枚举的思想依次对k比较
    //我们先测一下 Long.MAX_VALUE的阶乘后边有多少个0
    //Long.MAX_VALUE的阶乘后边有   2305843009213693937个0(10的19次方) > k
    //Long.MAX_VALUE/2的阶乘后边有 1152921504606846964个0(10的19次方) > k
    (所有在使用二分法时 有边界是Long.MAX_VALUE-5 左边界是1 不会有溢出)
​
    //因为N的阶乘后边有k个0 这个k随N的增大而增大 所以我们用二分查找
    //对于 100% 的数据,1 ≤ K ≤ 10的18次方
    //把l = 1作为最左边   r = Long.MAX_VALUE - 5;做为最右边
​
import java.util.Scanner;
 
 
public class Main {
    // 求x的阶乘后边有多少个0
    static long calc(long x){
        long res = 0;
        while (x!=0){
            res = res+x/5;
            x/=5;
        }
        return res;
    }
    //
    static void solve() {
        //第1部分代码
        //System.out.print(calc(10));//计算10的阶乘是不是后边有2个0
        //System.out.print(calc(25));//计算25的阶乘是不是后边有6个0
 
        //第2部分代码
        //System.out.print(calc(Long.MAX_VALUE/2 ));
        //Long.MAX_VALUE的阶乘后边有   2305843009213693937个0
        //Long.MAX_VALUE/2的阶乘后边有 1152921504606846964个0
 
        //二分查找
        Scanner scanner = new Scanner(System.in);
        long k = scanner.nextLong();
        long l = 1, r = Long.MAX_VALUE - 5;//l为最左边 r为最右边
        
        //long l = 1, r = 20;//方便学习可以debug
        while (l < r) {
            long mid = (l + r) / 2;
            if (k <= calc(mid)) {//如果mid的阶乘的0数大于等于k
                r = mid;//我们让r变为mid (可以等于mid)
            } else {//如果mid的阶乘的0数小于k
                l = mid + 1; //我们让l变为mid+1(大于mid,所以可以+1)
                //并且这里想让while循环中止就要不得不+1
            }
        }
        //二分法 l是最后的答案 
        if (calc(r) != k) {
            System.out.println(-1);
        } else {
            System.out.println(r);
        }
 
    }
    public static void main(String[] args) throws Exception{
        //System.out.println((Long.MAX_VALUE + 1)/2);
        // 大于Long.MAX_VALUE 会变成负数 所以有必要改进
        solve();
    }
}

陆续更新,敬请期待.......

试题 F: 最大子矩阵 题目:

 

解析: 试题 G:数组切分 题目:

 

解析: 试题 H: 回忆迷宫 题目:

解析: 试题 I: 红绿灯 题目:

 

解析: 试题 J: 拉箱子 题目:

 

解析:
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/855406.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号