蓝桥杯Java大学C组近三年真题解析(三)——暴力、模拟题

目录

第十届

求和

题目

题解

代码

矩形切割

题目

题解一

代码

代码

代码

题解二

代码

不同子串

题目

题解

代码

质数

题目

题解

代码

最大降雨量

题目

题解

代码

旋转

题目

题解

代码

外卖店优先级

题目

题解

代码

代码

代码

人物相关性分析

题目

题解

代码

总结

系列


第十届

求和

题目

题解

一道非常简单的题模拟寻找2、0、1、9的过程即可。答案:1905111

代码

public class Main {
    public static void main(String[] args) {
        String s;
        int sum = 0;
        for (int i = 1; i <= 2019; i++) {
            s = i + "";
            if (s.contains("0") || s.contains("1") || s.contains("2") || s.contains("9")) {
                sum += Integer.parseInt(s);
            }
        }
        System.out.println(sum);
    }
}

矩形切割

题目

题解一

根据题目的样例画图可知每次切割的正方形的边长是整个矩形中长的那一条边,并且最终得到的正方形数量是切割次数加或者说当长边和短边相等时还要加

答案:21

代码

public class Main {
    public static void main(String[] args) {
        int h = 2019, w = 324;
        int sum = 0;
        do {
            if (h > w) {
                h -= w;
            } else {
                w -= h;
            }
            sum++;
        } while (h != w);
        System.out.println(sum + 1);
    }
}

代码

public class Main {
    public static void main(String[] args) {
        int h = 2019, w = 324;
        int sum = 0;
        while (true) {
            sum++;
            if (h > w) {
                h -= w;
            } else if (w > h) {
                w -= h;
            }else {
                break;
            }
        }
        System.out.println(sum);
    }
}

代码

参考:https://www.lanqiao.cn/questions/194300/

public class Main {
    public static void main(String[] args) {
        System.out.println(qie(2019, 324));
    }

    /**
     * 每次递归就相当于与切割一次,每切割一次正方形个数加 1
     *
     * @param a 长边
     * @param b 短边
     * @return 切出正方形个数
     */
    static int qie(int a, int b) {
        if (a == b) {
            return 1;
        }
        return 1 + qie(Math.max(a - b, b), Math.min(a - b, b));
    }
}

题解二

根据题目的样例画图可知每次切割后多出的边是长边除短边 以5×3的矩形为例即:

第一次切割:5÷3=1……2——>得到新的边长2

第二次切割:3÷2=1……1——>得到新的边长1

第三次切割:2÷1=2……0——>得到新的边长0,说明此次切割得到的矩形是正方形不用再切割

分析可以发现整个过程就是求最大公约数,答案就是两边相除的商

参考:https://www.lanqiao.cn/questions/184683/

代码

public class Main {
    public static void main(String[] args) {
        gcd(2019, 324);
        System.out.println(count);
    }

    static int count = 0;

    public static int gcd(int a, int b) {
        if (b == 0) {
            return a;
        }
        count += a / b;
        return gcd(b, a % b);
    }
}

不同子串

题目

题解

一道非常简单的题目,两个for循环暴力破解,利用Set元素不重复的特性即可得到答案:100

因为substring()左闭右开的特点所以要注意for循环的范围,不要写错了!

代码

import java.util.HashSet;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        String s = "0100110001010001";
        Set<String> set = new HashSet<>();
        for (int i = 0; i < s.length(); i++) {
            for (int j = i + 1; j <= s.length(); j++) {
                set.add(s.substring(i, j));
            }
        }
        System.out.println(set.size());
    }
}

质数

题目

题解

这也是一道非常简单的题,for循环暴力查找即可 答案:17569

代码

public class Main {
    public static void main(String[] args) {
        int count = 1;
        boolean flag;
        for (int i = 3; ; i += 2) {
             flag = true;
            int t = (int) Math.sqrt(i);
            for (int j = 3; j <= t; j += 2) {
                if (i % j == 0) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                if (count == 2019 - 1) {
                    System.out.println(i);
                    return;
                }
                count++;
            }
        }
    }
}

最大降雨量

题目

题解

这道题的意思是将 1 到 49 分为7组数字,每组7个数字,求七组数字中每组数字的中位数所构成的数列的中位数的最大值。因为中位数是按顺序排列的一组数据中居于中间位置的数,所以这七组数据是顺序排列的,那么每组数列从后往前数,数到中位数就停下来,因为要保证中位数最大,中位数前面的数列任意即可。例如:

 图片中是其中一种情况。

也可以这样想:因为要保证所求中位数最大,所以要让所求中位数小于所求中位数所在行最后三位数,并且还要让所求中位数小于他之后所有行包括中位数在内的最后四位数

参考:https://www.lanqiao.cn/questions/185737/

代码

public class Main {
    public static void main(String[] args) {
        System.out.println(49 - (3 * 4 + 3));
    }
}

旋转

题目

题目描述

图片旋转是对图片最简单的处理方式之一,在本题中,你需要对图片顺时针旋转 90 度。

我们用一个 n×m 的二维数组来表示一个图片,例如下面给出一个 3×4 的 图片的例子:

1 3 5 7

9 8 7 6

3 5 9 7

这个图片顺时针旋转 90 度后的图片如下:

3 9 1

5 8 3

9 7 5

7 6 7

给定初始图片,请计算旋转后的图片。

输入描述

输入的第一行包含两个整数 n,m,分别表示行数和列数。

接下来 n 行,每行 m 个整数,表示给定的图片。图片中的每个元素(像 素)为一个值为 0 至 255 之间的整数(包含 0 和 255)。

输出描述

输出 m 行 n 列,表示旋转后的图片。

输入输出样例

示例

输入

3 4
1 3 5 7
9 8 7 6
3 5 9 7

输出

3 9 1
5 8 3
9 7 5
7 6 7

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

题解

这道题不难,不要看题目写那么多,其实这道题的目的就是将给的矩阵行变成列,列变成行

代码

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();
        int[][] a = new int[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                a[i][j] = sc.nextInt();
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = m - 1; j >= 0; j--) {
                System.out.print(a[j][i] + " ");
            }
            System.out.println();
        }
    }
}

外卖店优先级

题目

题目描述

"饱了么"外卖系统中维护着 N 家外卖店,编号 1 ∼ N。每家外卖店都有 一个优先级,初始时 (0 时刻) 优先级都为 0。

每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减 到 0;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 2。

如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中;如果 优先级小于等于 3,则会被清除出优先缓存。

给定 T 时刻以内的 M 条订单信息,请你计算 T 时刻时有多少外卖店在优 先缓存中?

输入描述

第一行包含 3 个整数 N,M,T。

以下 M 行每行包含两个整数 ts,id,表示 ts 时刻编号 id 的外卖店收到一个订单。

其中,1≤N,M,T≤10^5,1≤ts≤T,1≤id≤N。

输出描述

输出一个整数代表答案。

输入输出样例

示例

输入

2 6 6
1 1
5 2
3 1
6 2
2 1
6 2

输出

1

样例解释:

6 时刻时,1 号店优先级降到 3,被移除出优先缓存;2 号店优先级升到 6, 加入优先缓存。所以是有 1 家店 (2 号) 在优先缓存中。

运行限制

  • 最大运行时间:2s
  • 最大运行内存: 256M

题解

这道题没有什么高大上的解法(目前没看到),就是模拟题目描述的过程。蓝桥杯给的难度是:中等、标签是:模拟蓝桥杯的模拟类的题目也不一定是简单题。这道题才算是真正考察我们将某个事件抽象成程序的能力。

这道题蓝桥云课的测试数据很水,建议去试题集的历届真题测试更好。

写了不少蓝桥杯题目,很少碰到运行时间允许在 3s 以内的题,正好这道题就是。所以我使用了快读,毕竟是提到模拟类的题就怕超时

详细的过程代码的注释写的很清楚,这里就不在重复。

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;

public class Main {
    static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

    static int nextInt() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }

    public static void main(String[] args) throws IOException {
        // n 家外卖店
        int n = nextInt();
        // m 条订单信息
        int m = nextInt();
        // t 时刻以内
        int t = nextInt();
        // 存储 m 条订单信息
        int[][] order = new int[m][2];

        // 输入订单信息
        for (int i = 0; i < order.length; i++) {
            for (int j = 0; j < order[i].length; j++) {
                order[i][j] = nextInt();
            }
        }

        // 根据订单时间升序排序,时间相同根据外卖店 id 升序排序
        Arrays.sort(order, (e1, e2) -> (e1[0] == e2[0] ? (e1[1] - e2[1]) : (e1[0] - e2[0])));

        // 外卖店 id
        int shop;
        // 外卖店优先级
        int[] priority = new int[n];
        // 是否在优先缓存中 1表示在优先缓存中 0表示不在优先缓存中
        int[] cache = new int[n];
        // 最大时间就是上面时刻排序后的最后一个值
        for (int i = 1; i <= order[m - 1][0]; i++) {
            // 外卖店在该时刻是否有订单
            boolean[] isOrder = new boolean[n];
            for (int j = 0; j < order.length; j++) {
                if (order[j][0] >= i) {
                    // 时间相等则有订单
                    if (order[j][0] == i) {
                        // 获取外卖店 id
                        shop = order[j][1];
                        // 当前时刻该外卖店有订单
                        isOrder[shop - 1] = true;
                        // 当前时刻该外卖店有订单则优先级增加 2
                        priority[shop - 1] += 2;
                        // 如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中
                        if (priority[shop - 1] > 5) {
                            cache[shop - 1] = 1;
                        }
//                        想继续优化减少运行时间,结果是反向优化,运行时间更长了,但是在某些测试样例还是有用的
//                        if (j + 1 != order.length) {
//                            continue;
//                        }
                    }
                    if (order[j][0] > i || j + 1 == order.length) {
                        for (int k = 0; k < n; k++) {
                            // 如果外卖店没有订单,则优先级会减少 1
                            if (!isOrder[k] && priority[k] > 0) {
                                priority[k]--;
                            }
                            // 如果优先级小于等于 3,则会被清除出优先缓存
                            if (priority[k] <= 3 && cache[k] == 1) {
                                cache[k] = 0;
                            }
                        }
                        break;
                    }
                }
            }
        }
        int sum = 0;
        for (int j : cache) {
            sum += j;
        }
        System.out.println(sum);
    }
}

参考:我同学写的,上面的代码是我优化后的

看到有两位大佬的题解实现了时间和空间极致压缩,下面的代码是我稍微优化了一下运行时间快了一点点,感兴趣可以动手测试一下。

代码

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;

public class Main {
    static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

    static int nextInt() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }

    /**
     * T 时刻以内
     */
    static int T;

    public static void main(String[] args) throws IOException {
        // n 家外卖店
        int n = nextInt();
        // m 条订单信息
        int m = nextInt();
        // T 时刻以内
        T = nextInt();
        // 根据外卖店 id 存储订单信息
        ArrayList<Integer>[] a = new ArrayList[n + 1];
        for (int i = 1; i <= n; i++) {
            a[i] = new ArrayList();
        }
        // ts 时刻编号 id 的外卖店收到一个订单
        int ts, id;
        while (m-- > 0) {
            ts = nextInt();
            id = nextInt();
            a[id].add(ts);
        }
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            // 将每个外卖店有订单的时刻按时间升序排序
            Collections.sort(a[i]);
            if (check(a[i])) {
                ans++;
            }
        }
        System.out.println(ans);
    }

    public static boolean check(ArrayList<Integer> list) {
        // 该外卖店在T时刻以内订单总数
        int n = list.size();
        // 该外卖店在T时刻以内订单数量 <=2 优先级最多为 4 不可能加入优先缓存中
        if (n <= 2) {
            return false;
        }
        // 外卖店优先级
        int sum = 2;
        // 是否在优先缓存中
        // 默认优先级小于等于 3,被清除出优先缓存
        boolean flag = false;
        // 外卖店前后连续两次有订单的时刻
        int pre, cur;
        for (int i = 0; i + 1 < n; i++) {
            pre = list.get(i);
            cur = list.get(i + 1);
            if (pre != cur) {
                // 如果外卖店没有订单,则优先级会减少 1,最低减到 0
                // pre != cur 说明pre时刻到cur时刻内有某时刻外卖店没有订单,则优先级会减少对应时刻
                sum = Math.max(sum - (cur - pre - 1), 0);
            }
            // 当前时刻该外卖店有订单则优先级增加 2
            sum += 2;
        }
        // 如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中
        if (sum > 5) {
            flag = true;
        }
        // 当前外卖店所有订单优先级计算完后,还需计算最后有订单的时刻到 T 时刻内没有订单的时刻要减少多少优先级
        sum -= (T - list.get(n - 1));
        // 如果优先级小于等于 3,则会被清除出优先缓存
        if (sum <= 3) {
            flag = false;
        }
        return flag;
    }
}

参考:https://www.lanqiao.cn/questions/227570/

代码

import java.io.*;
import java.util.*;

public class Main {
    static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

    static int nextInt() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }

    public static void main(String[] args) throws IOException {
        int N = nextInt();
        int M = nextInt();
        int T = nextInt();
        int[] p = new int[N + 1];
        boolean[] incache = new boolean[N + 1];
        //**创建二维不定长数组
        List<Integer>[] g = new ArrayList[N + 1];
        for (int i = 1; i <= N; i++) {
            g[i] = new ArrayList<>();
        }
        for (int i = 0; i < M; i++) {
            int ts = nextInt();
            int id = nextInt();
            g[id].add(ts);
        }
        int ans = 0;
        for (int i = 1; i <= N; i++) {
            int size = g[i].size();
            if (size == 0) {
                continue;
            }
            //按时间排下序
            Collections.sort(g[i]);
            //获取i号店的第一个订单时刻
            int now = g[i].get(0);
            int pre = now;
            for (int j = 0; j < size; j++) {
                now = g[i].get(j);
                int cha = now - pre;
                if (cha != 0 && cha != 1) {
                    p[i] -= cha - 1;
                    if (p[i] < 0) {
                        p[i] = 0;
                    }
                    if (p[i] <= 3) {
                        incache[i] = false;
                    }
                }
                p[i] += 2;
                if (p[i] > 5) {
                    incache[i] = true;
                }
                pre = now;
            }
            int cha = T - pre;
            if (cha > 0) {
                p[i] -= cha;
                if (p[i] <= 3) {
                    incache[i] = false;
                }
            }
            if (incache[i]) {
                ans++;
            }
        }
        System.out.println(ans);
    }
}

参考:https://blog.dotcpp.com/a/72220

人物相关性分析

题目

题目描述

小明正在分析一本小说中的人物相关性。他想知道在小说中 Alice 和 Bob 有多少次同时出现。

更准确的说,小明定义 Alice 和 Bob "同时出现" 的意思是:在小说文本 中 Alice 和 Bob 之间不超过 K 个字符。

例如以下文本:

This is a story about Alice and Bob.Alice wants to send a private message to Bob.

假设 K = 20,则 Alice 和 Bob 同时出现了 2 次,分别是"Alice and Bob" 和 "Bob. Alice"。前者 Alice 和 Bob 之间有 5 个字符,后者有 2 个字符。

注意:

  1. Alice 和 Bob 是大小写敏感的,alice 或 bob 等并不计算在内。

  2. Alice 和 Bob 应为单独的单词,前后可以有标点符号和空格,但是不能 有字母。例如 Bobbi 並不算出现了 Bob。

输入描述

第一行包含一个整数 K(1≤K≤106)。

第二行包含一行字符串,只包含大小写字母、标点符号和空格。长度不超过 10^6。

输出描述

输出一个整数,表示 Alice 和 Bob 同时出现的次数。

输入输出样例

示例

输入

20
This is a story about Alice and Bob.Alice wants to send a private
message to Bob.

输出

2

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 512M

题解

这道模拟类的题暴力破解一定可以得到部分的分数,比如我在C语言网纯暴力破解测试得分有80+的分数,不出意外是超时这也是这道题的难点,因为暴力破解不得不考虑时间问题,而这道题的时间限制是 1s ,与上一题相比这道题的时间卡的很死。这道题我没想到是用到了滑动窗口或者叫尺取法,这里我就不献丑了,直接看y总的视频在29:52开始讲解本题。我看了网上其他人的题解,不是超时就是内存超限,能AC的代码基本都可以是y总视频中讲的方法,y总yyds

另外说一下,在蓝桥杯的试题集提交本题的话始终是零分,一开始以为是我有问题直到我看了测试用例

输入:

3
1 1 1

输出:

3
看完我都不知道说什么好输入的完全牛头不对马嘴,每年收那么多钱就不能认真干活,不愧被称为圈钱杯(垃圾蓝桥杯狗都不参加)

代码

import java.io.*;
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int k = Integer.parseInt(br.readLine());
        String str = br.readLine();
        ArrayList<Integer> a = new ArrayList<>();
        ArrayList<Integer> b = new ArrayList<>();
        for (int i = 0; i + 5 <= str.length(); i++) {
            if ((i == 0 || check(str.charAt(i - 1))) && ((i + 5) == str.length() || check(str.charAt(i + 5)))) {
                if ("Alice".equals(str.substring(i, i + 5))) {
                    a.add(i);
                }
            }
        }
        for (int i = 0; i + 3 <= str.length(); i++) {
            if ((i == 0 || check(str.charAt(i - 1))) && ((i + 3) == str.length() || check(str.charAt(i + 3)))) {
                if ("Bob".equals(str.substring(i, i + 3))) {
                    b.add(i);
                }
            }
        }
        long res = 0;
        for (int i = 0, l = 0, r = -1; i < a.size(); i++) {
            while (r + 1 < b.size() && a.get(i) >= b.get(r + 1)) {
                r++;
            }
            while (l <= r && a.get(i) - 1 - (b.get(l) + 3) + 1 > k) {
                l++;
            }
            res += r - l + 1;
        }
        for (int i = 0, l = 0, r = -1; i < b.size(); i++) {
            while (r + 1 < a.size() && b.get(i) >= a.get(r + 1)) {
                r++;
            }
            while (l <= r && b.get(i) - 1 - (a.get(l) + 5) + 1 > k) {
                l++;
            }
            res += r - l + 1;
        }
        System.out.println(res);
    }

    private static boolean check(char c) {
        return (c < 'a' || c > 'z') && (c < 'A' || c > 'Z');
    }
}

参考:https://www.lanqiao.cn/questions/227649/ 

总结

这些题在第十届中除了最后两题属于简单题(我认为不是),在考试中应该是必拿的分考的是我们模拟某种事件将其转换为程序的能力和发现规律的能力,此类题型一般是填空题或数据范围较小的编程题(最后两题不按套路来),因为暴力模拟一般会超时

其他题目持续更新中。。。。。。

系列

蓝桥杯Java大学C组近三年真题解析(一)——暴力、模拟题_疯狂的格式化的博客-CSDN博客

蓝桥杯Java大学C组近三年真题解析(二)——暴力、模拟题_疯狂的格式化的博客-CSDN博客

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值