蓝桥杯2019JavaB部分题解(最喜欢暴力了)

B:不同子串

【问题描述】

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

       一定注意这里的要求,长度为1从头到尾循环一遍,长度+1再循环一遍,直到长度等于字符串的长度;而不是长度不断递增但不从头到尾循环。hashset的特点就是排除重复元素。

代码:

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

C:数列求值

【问题描述】

       给定数列 1,1,1,3,5,9,17, …,从第4 项开始,每项都是前 3 项的和。求第 20190324 项的最后 4 位数字。

       说白了,这道题目还是考察思维。

       这里一直单纯地加到2千万项后数字会大的离谱,甚至会超过编辑器所允许程序BigInteger类所使用的最大内存,从而报错(当然也可以设置扩大可用内存...)。题目中只需要最后4位数字是关键,我们只需截取每次计算的最后4位即可,即 / 10000。

代码:

public class Main {
	public static void main(String[] args) {
		int a = 1;
		int b = 1;
		int c = 1;
		int n = 20190324;
		for(int i = 4; i <= n; i++) {
        // 每次一个数的值等于前三个数的和
        // 即 a b c a b c a b c 循环
        //    1 2 3 4 5 6 7 8 9
        // 故只判断这个数与3的关系即可
			if (i % 3 == 1) {
				a = (a + b + c) % 10000;
			} else if(i % 3 == 2) {
				b = (a + b + c) % 10000;
			} else {
				c = (a + b + c) % 10000;
			}
		}
		System.out.println(c);
	}
}

 D:数的分解

【问题描述】

       把 2019 分解成 3 个各不相同的正整数之和,并且要求每个正整数都不包含数字 2 和 4,一共有多少种不同的分解方法?
       注意交换 3 个整数的顺序被视为同一种方法,例如 1000 + 1001 + 18 和 1001 + 1000 + 18 被视为同一种。

       注意这里要求3个数各不相同,全排列共有6种可能(ABC、ACB、BAC、BCA、CAB、CBA),但题目又限制交换顺序只算一种。可以算出结果再÷6,另一种不容易想到的方法是规定ABC的大小关系,这样即可保证题目的要求。

代码:

public class Main {
	public static void main(String[] args) {
		int sum = 0;
		int n = 2019;
		for (int i = 1; i <= n; i++) {
			for (int j = i + 1; j < n - i - j; j++) {
				int k = n - i - j;
				if (check(i) && check(j) && check(k)) {
					sum++;
				}
			}
		}
		System.out.println(sum);
	}

	public static boolean check(int num) {
		while (num > 0) {
			int m = num % 10;
			if (m == 2 || m == 4) {
				return false;
			}
			num = num / 10;
		}
		return true;
	}
}

F:特别数的和

【问题描述】
       小明对数位中含有 2、0、1、9 的数字很感兴趣(不包括前导 0),在 1 到40 中这样的数包括 1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574。
       请问,在 1 到 n 中,所有这样的数的和是多少?

【输入格式】
       输入一行包含两个整数 n。
【输出格式】
       输出一行,包含一个整数,表示满足条件的数的和。
【样例输入】
       40
【样例输出】
       574
【评测用例规模与约定】
       对于 20% 的评测用例,1 ≤ n ≤ 10。
       对于 50% 的评测用例,1 ≤ n ≤ 100。
       对于 80% 的评测用例,1 ≤ n ≤ 1000。
       对于所有评测用例,1 ≤ n ≤ 10000。

代码:

public class Main {

	public static void main(String[] args) {
		int n = 0;
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		int sum = 0;
		for (int i = 1; i <= n; i++) {
			if (check(i)) {
				sum += i;
			}
		}
		System.out.println(sum);
	}

	public static boolean check(int n) {
		while (n > 0) {
			int num = n % 10;
			if (num == 2 || num == 9 || num == 1 || num == 0) {
				return true;
			}
			n = n / 10;
		}
		return false;
	}
}

G:外卖店优先级

【问题描述】

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

【输入格式】
       第一行包含3 个整数N、M 和T。
       以下M 行每行包含两个整数ts 和id,表示ts 时刻编号id 的外卖店收到一个订单。
【输出格式】
       输出一个整数代表答案。
【样例输入】
       2 6 6
       1 1
       5 2
       3 1
       6 2
       2 1
       6 2

【样例输出】
       1

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

       这道题想了很久,没忍住看了一下答案思路。。。

       大致是创建一个数组来存储每个店铺每个时刻的订单个数,默认为0,有订单则++。此外,使用Math函数的max方法完成优先级的加减。

       个人觉得在做这类题目(或者所有蓝桥杯的题目)的时候需要先理清思路,先想通,再一步一步去实现就很容易了。对于一些不太好想的题目,推荐举一个简单例子,通过画图,更直观地弄明白题目意思和要求,同时也更容易找到解题思路。

上代码:

public class Main {

	public static void main(String[] args) {
		int n, m, t;
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();// 店的个数
		m = sc.nextInt();// 订单的个数
		t = sc.nextInt();// 时刻
		int ts = 0;
		int id = 0;
		int[][] arr = new int[n][t];
		for (int i = 0; i < m; i++) {
			ts = sc.nextInt();// ts时刻
			id = sc.nextInt();// 店id
			arr[id - 1][ts - 1]++;
		}
		arr[0][0] = Math.max(arr[0][0] == 0 ? -1 : arr[0][0] * 2, 0);
		arr[1][0] = Math.max(arr[1][0] == 0 ? -1 : arr[1][0] * 2, 0);
		int res = n;
		for (int i = 0; i < n; i++) {
			for (int j = 1; j < t; j++) {
				arr[i][j] = Math.max(arr[i][j - 1] + (arr[i][j] == 0 ? -1 : arr[i][j] * 2), 0);
//				System.out.print(arr[0][0]);
//				System.out.print(arr[1][0]);
//				System.out.print(arr[i][j] + " ");
			}
//			if(arr[i][t] <= 3) { // Index 6 out of bounds for length 6 因为t = 6,但最后一个元素的下标为5
			if (arr[i][t - 1] <= 3) {
				res--;
			}
		}
		for (int k1 = 0; k1 < n; k1++) {
			for (int k2 = 0; k2 < t; k2++) {
				System.out.print(arr[k1][k2] + " ");
			}
			System.out.println();
		}
		System.out.println();
		System.out.println(res);
	}
}

I:后缀表达式

【问题描述】
       给定 N 个加号、 M 个减号以及 N + M + 1 个整数 A1,A2,......,A(N + M + 1),小明想知道在所有由这 N 个加号、 M 个减号以及 N + M +1 个整数凑出的合法的后缀表达式中,结果最大的是哪一个?
       请你输出这个最大的结果。
       例如使用 1 2 3 + - ,则 “ 2 3 + 1 - ” 这个后缀表达式结果是 4 ,是最大的。

【输入格式】
       第一行包含两个整数 N 和 M 。
       第二行包含 N + M + 1 个整数 A1,A2,......,A(N + M + 1)。
【输出格式】
       输出一个整数,代表答案。

【数据范围】

       0 ≤ N,M ≤ 10^5,

       -10^9 ≤ Ai ≤ 10^9
【样例输入】
       1 1
       1 2 3
【样例输出】
       4

       这个题不要想复杂了,题目要求结果最大,很容易能想到把最大的数相加,减去最小的数最后的结果最大。而想得到最大和最小的数很容易想到Arrays数组中的sort方法。只要判断具体的+、-符号的个数进行数学运算即可。

       举例画图:

上代码:

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();// +
		int m = sc.nextInt();// -
		int a = m + n + 1;
		int[] arr = new int[a];
		for(int i = 0; i < arr.length; i++) {
			arr[i] = sc.nextInt();
		}
		Arrays.sort(arr);
//		for(int i = 0; i < arr.length; i++) {
//			System.out.println(arr[i]);
//		}
		int res = 0;
		for(int i = arr.length - 1; i > arr.length - 1 - 1 - n; i--) {
			res += arr[i];// 搞不清length减几就举例子、画图
		}
//		System.out.println(res);
		for(int i = 0; i < arr.length - n - 1; i++) {
			res -= arr[i];// 也可以再搞一个res2,再把减的数都加起来,最后用res - res2
		}
		System.out.println(res);
	}
}

 123456

如果觉得本篇内容还不错的话,可否来个👍支持一下呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值