蓝桥杯 2019年省赛真题 (Java 大学C组)

蓝桥杯 2019 年省赛真题(Java 大学 C 组 )

    • #A 求和
    • #B 矩形切割
    • #C 不同子串
    • #D 质数
    • #E 最大降雨量
    • #F 旋转
    • #G 外卖店优先级
    • #H 人物相关性分析
    • #I 等差数列
    • #J 扫地机器人


#A 求和

本题总分:5 分


问题描述

小明对数位中含有 2、0、1、9 的数字很感兴趣,在 1 到 40 中这样的数包 括 1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574。 请问,在 1 到 2019 中,所有这样的数的和是多少?


答案提交

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分


1905111

calcCode:

public class Test {
     
	
	public static void main(String[] args) {
     
		int H = 2019, cnt = 0;
		for (int i = 1; i <= H; i++)
			if (check(i)) cnt += i;
		System.out.print(cnt);
	}
	
	static boolean check(int n) {
     
		do switch (n % 10) {
     
			case 2:
			case 0:
			case 1:
			case 9: return true; 
		} while (0 != (n /= 10));
		return false;
	}
}

校验写在方法里更好跳出一点


#B 矩形切割

本题总分:5 分


问题描述

小明有一些矩形的材料,他要从这些矩形材料中切割出一些正方形。
当他面对一块矩形材料时,他总是从中间切割一刀,切出一块最大的正方 形,剩下一块矩形,然后再切割剩下的矩形材料,直到全部切为正方形为止。 例如,对于一块两边分别为 5 和 3 的材料(记为 5×3),小明会依次切出 3×3、2×2、1×1、1×1 共 4 个正方形。 现在小明有一块矩形的材料,两边长分别是 2019 和 324。请问小明最终会 切出多少个正方形?


答案提交

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。


21

calcCode:

public class Test {
     
	
    public static void main(String[] args) {
      System.out.println(calc(2019, 324)); }
    
    static int calc(int a, int b) {
      return a == b? 1: (1 + (a > b? calc(a - b, b): calc(a, b - a))); }
}

优雅


#C 不同子串

本题总分:10 分


问题描述

一个字符串的非空子串是指字符串中长度至少为 1 的连续的一段字符组成 的串。例如,字符串aaab 有非空子串a, b, aa, ab, aaa, aab, aaab,一共 7 个。 注意在计算时,只算本质不同的串的个数。 请问,字符串0100110001010001 有多少个不同的非空子串?


答案提交

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。


100

calcCode:

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

public class Test {
     
	
	static Set<String> set;
	static String str = "0100110001010001";
	
	public static void main(String[] args) {
     
		set = new HashSet();
		dfs(0, 0);
		set.remove("");
		System.out.print(set.size());
	}
	
	static void dfs(int d, int start) {
     
		if (d == str.length()) set.add(str.substring(start));
		else {
     
			set.add(str.substring(start, d));
			dfs(d + 1, d);
			dfs(d + 1, start);
		}
	}
}

不可思议,这有 100 个子串


#D 质数

本题总分:10 分


问题描述

我们知道第一个质数是 2、第二个质数是 3、第三个质数是 5……请你计算 第 2019 个质数是多少?


答案提交

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。


17569

calcCode:

public class Test {
     
	
	public static void main(String[] args) {
     
		int[] a = new int[2020];
		a[1] = 2;
		agent: for (int i = 2, n = 3; i <= 2019; n += 2) {
     
			int h = (int)Math.sqrt(n), j = 0;
			while (a[++j] <= h)
				if (n % a[j] == 0) continue agent;
			a[i++] = n;
		}
		System.out.print(a[2019]);
	}
}

除试法打表,完事


#E 最大降雨量

本题总分:15 分


问题描述

由于沙之国长年干旱,法师小明准备施展自己的一个神秘法术来求雨。 这个法术需要用到他手中的 49 张法术符,上面分别写着 1 至 49 这 49 个 数字。法术一共持续 7 周,每天小明都要使用一张法术符,法术符不能重复使 用。 每周,小明施展法术产生的能量为这周 7 张法术符上数字的中位数。法术 施展完 7 周后,求雨将获得成功,降雨量为 7 周能量的中位数。 由于干旱太久,小明希望这次求雨的降雨量尽可能大,请大最大值是多少?


答案提交

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。


34

calcCode:

System.out.print(7 * 7 - 4 * 4 + 1);

蓝桥杯 2019年省赛真题 (Java 大学C组)_第1张图片
图做的有点大 . . .

如果选择 7 位数字,使其递增排序后,中位数最大
这个 7 个数字中,前 3 位的选择是没有意义的
而中位数必然是该序列后 4 位最小

把这个思路放大到题目给定的矩阵里,答案就出来了


#F 旋转

时间限制: 1.0s 内存限制: 512.0MB 本题总分:15 分


问题描述

图片旋转是对图片最简单的处理方式之一,在本题中,你需要对图片顺时 针旋转 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 列,表示旋转后的图片。


测试样例1

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

Output:
3 9 1
5 8 3
9 7 5
7 6 7

评测用例规模与约定

对于 30% 的评测用例,1≤n,m≤10。
对于 60% 的评测用例,1≤n,m≤30。
对于所有评测用例,1≤n,m≤100。


code:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class Main {
     
	
    public static void main(String[] args) throws IOException {
     
    	BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    	StringTokenizer line = new StringTokenizer(in.readLine());
    	PrintWriter out = new PrintWriter(System.out);
        int n = Integer.parseInt(line.nextToken());
        int m = Integer.parseInt(line.nextToken());
        String[][] buff = new String[m][n];
        for (int j = n - 1; j >= 0; j--) {
     
        	line = new StringTokenizer(in.readLine());
        	for (int i = 0; i < m; i++)
        		buff[i][j] = line.nextToken();
        }
        for (int i = 0; i < m; i++) {
     
        	for (int j = 0; j < n; j++) {
     
        		out.print(buff[i][j]);
        		out.write(' ');
        	}
        	out.write('\n');
        }
        out.close();
    }
}

第一行变最后一列,以此类推,改变存储输入的顺序就行,再就是不需要保存为整形

因为该题里单元的值对于旋转是没有帮助的,虽然在一定程度上能减少内存的开销,但还要考虑到 输入流的计算 和 String.valueOf 的计算时间


#G 外卖店优先级

时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分


问题描述

“饱了么”外卖系统中维护着 N 家外卖店,编号 1 ∼ N。每家外卖店都有 一个优先级,初始时 (0 时刻) 优先级都为 0。 每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减 到 0;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 2。 如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中;如果 优先级小于等于 3,则会被清除出优先缓存。 给定 T 时刻以内的 M 条订单信息,请你计算 T 时刻时有多少外卖店在优 先缓存中。


输入格式

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


输出格式

输出一个整数代表答案。


测试样例1

Input:
2 6 6
1 1
5 2
3 1
6 2
2 1
6 2

Output:
1

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

评测用例规模与约定

对于 80% 的评测用例, 1 ≤ N; M; T ≤ 10000。
对于所有评测用例, 1 ≤ N; M; T ≤ 100000, 1 ≤ ts ≤ T, 1 ≤ id ≤ N。


code:

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

public class Main {
     

    static final int TMod = 131071;

    public static void main(String[] args) throws IOException {
     
        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        int res = 0;
        in.nextToken();
        in.nextToken();
        int m = (int)in.nval;
        in.nextToken();
        int t = (int)in.nval;
        int[] queue = new int[m + 1];
        queue[m] = Integer.MAX_VALUE;
        for (int i = 0, T; i < m; i++) {
     
            in.nextToken();
            T = (int)in.nval;
            in.nextToken();
            queue[i] = ((int)in.nval << 17) | T;
        }
        Arrays.sort(queue);
        boolean last = false;
        for (int i = 0, pre = 0, now, preI = 0, preT = 0, cnt = 0; i <= m; i++) {
     
            now = queue[i];
            if (pre == now) cnt += 2;
            else if (now >> 17 > preI) {
     
                if (t > preT) cnt -= t - preT;
                if (cnt > 5 || (last && cnt > 3)) res++;
                preT = now & TMod;
                preI = now >> 17;
                cnt = 2;
                continue;
            } else {
     
                cnt += preT;
                preT = now & TMod;
                cnt -= preT - 1;
                if (cnt <= 3) last = false;
                if (cnt <= 0) cnt = 2;
                else cnt += 2;
            }
            if (cnt > 5) last = true;
            else if (cnt < 0) cnt = 0;
            else if (cnt <= 3) last = false;
            pre = now;
        }
        System.out.print(res);
    }
}

读完题我就觉得,店家数这个变量没有实际作用,因为店家之间是不会相互影响的,不会因为某个时间段优先缓存拥挤就改变进出的条件

再就是一个 1E4 一个 1E5 拿测试类算了一下,正好可以放进 31 位整形里(不要符号位是因为不便于比较)

Ts | id << 17 拿到的结果直接进行值比较,等价于
this.id == arg.id? this.Ts - arg.Ts: this.id - arg.id

然后该怎么模拟怎么模拟,修饰一下细节就大功告成了

生成了最大约定的数据,测测速

PrintWriter out = new PrintWriter(new FileOutputStream("data.txt"));
out.println("10000 100000 10");
Random random = new Random();
for (int i = 0; i < 100000; i++)
	out.println(random.nextInt(100000) + " " + (random.nextInt(10) + 1));
out.close();

毫秒级的响应,去网上找三两人代码,生成一个高度随机的看看结果

发现结果不对 debug 半天,两个整形整合到一个整形,找的我头皮发麻

更头皮发麻的是题没读全,一个订单增加 2 而不是 1

这个故事告诉我们审题一定要谨慎谨慎再谨慎


#H 人物相关性分析

时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分


问题描述

小明正在分析一本小说中的人物相关性。他想知道在小说中 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。
第二行包含一行字符串,只包含大小写字母、标点符号和空格。长度不超过 1000000。


输出格式

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


测试样例1

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

Output:
2

评测用例规模与约定

对于所有评测用例, 1 ≤ K ≤ 1000000。


code:

import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;

public class Main {
     

    static final char[] bob = {
      'B', 'o', 'b' };
    static final char[] alice = {
      'A', 'l', 'i', 'c', 'e' };

    public static void main(String[] args) throws IOException {
     
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int k = Integer.parseInt(in.readLine()), cnt = 0;
        Queue<Integer> preA = new LinkedList();
        Queue<Integer> preB = new LinkedList();
        String story = in.readLine();
        int high = story.length();
        for (int i = 0, a = 0, b = 0; i < high; i++) {
     
            char now = story.charAt(i);
            if (preA.size() > 0 && preA.peek() + k + 3 < i) preA.poll();
            if (preB.size() > 0 && preB.peek() + k + 5 < i) preB.poll();
            if (now == alice[a++]) {
     
                if (a == 1 &&  isLetter(i > 0? story.charAt(i - 1): ' ')) a = 0;
                else if (a == 5) {
     
                    a = 0;
                    preA.offer(i);
                    cnt += preB.size();
                }
            } else if (now == bob[b++]) {
     
                a = 0;
                if (b == 1 &&  isLetter(i > 0? story.charAt(i - 1): ' ')) b = 0;
                else if(b == 3) {
     
                    b = 0;
                    preB.offer(i);
                    cnt += preA.size();
                }
            } else a = b = 0;
        }
        System.out.println(cnt);
    }

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

要你只记录新项能组成个数,记录结果就不会重复

也没啥好说的,字符串处理最好还是交给API来处理,这里可以提高稳定性


#I 等差数列

时间限制: 1.0s 内存限制: 512.0MB 本题总分:25 分


问题描述

数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一 部分的数列,只记得其中 N 个整数。
现在给出这 N 个整数,小明想知道包含这 N 个整数的最短的等差数列有几项?


输入格式

输入的第一行包含一个整数 N。
第二行包含 N 个整数 A1,A2,··· ,AN。(注意 A1 ∼ AN 并不一定是按等差数 列中的顺序给出)


输出格式

输出一个整数表示答案。


测试样例1

Input:
5
2 6 4 10 20

Output:
10

Explanation:
包含 2、6、4、10、20 的最短的等差数列是 2、4、6、8、10、12、14、16、18、20。

评测用例规模与约定

对于所有评测用例,2≤ N ≤100000,0≤ Ai ≤109。


code:

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

public class Main {
     

    public static void main(String[] args) throws IOException {
     
    	StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    	int n, gcd, arr[];
    	in.nextToken();
    	n = (int)in.nval;
    	arr = new int[n];
    	for (int i = 0; i < n; i++) {
     
    		in.nextToken();
    		arr[i] = (int)in.nval;
    	}
    	Arrays.sort(arr);
    	gcd = arr[1] - arr[0];
    	if (gcd == 0) System.out.print(n);
    	else {
     
    		for (int i = 2; i < n; i++)
    			gcd = gcd(gcd, arr[i] - arr[i - 1]);
    		System.out.println((arr[n - 1] - arr[0]) / gcd + 1);
    	}
    }

    static int gcd(int a, int b) {
      return b == 0 ? a: gcd(b, a % b); }
}

可能的最大公差就是相邻项差这个集合的最大公约数

虽然这属于比较入门比较简单的,但没办法就是怕这种题
完了啊,到我登场的时候暴力杯越来越不像暴力杯了啊

呜呼哀哉


#J 扫地机器人

时间限制: 1.0s 内存限制: 512.0MB 本题总分:25 分


问题描述

小明公司的办公区有一条长长的走廊,由 N 个方格区域组成,如下图所
示。
走廊内部署了 K 台扫地机器人,其中第 i 台在第 Ai 个方格区域中。 已知扫地机器人每分钟可以移动到左右相邻的方格中,并将该区域清扫干
净。
请你编写一个程序,计算每台机器人的清扫路线,使得

  1. 它们最终都返回出发方格,
  2. 每个方格区域都至少被清扫一遍,
  3. 从机器人开始行动到最后一台机器人归位花费的时间最少。

注意多台机器人可以同时清扫同一方块区域,它们不会互相影响。
输出最少花费的时间。 在上图所示的例子中,最少花费时间是 6。第一台路线:2-1-2-3-4-3-2,清 扫了 1、2、3、4 号区域。第二台路线 5-6-7-6-5,清扫了 5、6、7。第三台路线 10-9-8-9-10,清扫了 8、9 和 10。


输入格式

第一行包含两个整数 N 和 K。 接下来 K 行,每行一个整数 Ai。


输出格式

输出一个整数表示答案。


测试样例1

Input:
10 3
5
2
10

Output:
6

评测用例规模与约定

对于 30% 的评测用例,1≤ K < N ≤10。
对于 60% 的评测用例,1≤ K < N ≤1000。
对于所有评测用例,1≤ K < N ≤100000,1≤ Ai ≤ N。


code:

import java.io.IOException;
import java.io.BufferedReader;
import java.io.StreamTokenizer;
import java.io.InputStreamReader;
import java.util.Arrays;
 
public class Main {
     
	
    public static void main(String[] args) throws IOException {
     
    	StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        in.nextToken();
        int n = (int)in.nval;
        in.nextToken();
        int k = (int)in.nval;
        if (k == 1) System.out.println((n << 1) - 2);
        else {
     
        	int[] bot = new int[k];
            for (int i = 0; i < k; i++) {
     
            	in.nextToken();
            	bot[i] = (int)in.nval;
            }
            Arrays.sort(bot, 0, k);
            int time = max(n / k, max(bot[0], n - bot[k - 1])) - 1, end = 0;
            agent: while (end < n) {
     
            	end = 0;
            	time++;
            	for (int i = 0; i < k; i++) {
     
            		if (bot[i] - time > end) continue agent;
            		else end = bot[i] <= end? bot[i] + time - 1 : end + time;
            	}
            }
            System.out.println((time << 1) - 2);
        }
    }
    
    static int max(int a, int b) {
      return a > b ? a : b; }
}

芜湖,熟悉的暴力杯,对8起

首先确定最少要走的路程,理想情况下当然是 长度除以机器人个数乘以二,当然然也有极端情况

想要最高效率那两端的清洁必须交给两端的机器人,然而机器人清理完还有返回的命令,所以最少要走过这段路程

接下来每个机器人尽可能的完成任务,如果不能达成每个方格至少清扫一次的任务的话,就跳过

因为机器人需要返回,所以它的行走次数必然是个偶数,+=2 比较合理

完事


你可能感兴趣的:(java)