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);
}
}
如果觉得本篇内容还不错的话,可否来个👍支持一下呢?