文章目录
- 🧡🧡t1_字母数🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t2_大乘积🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t3_星期几🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t4_列名🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t5_清理水域🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t6_最大连通🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t7_信号覆盖🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t8_附近最小🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t9_特殊日期🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t10_第三小🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t11_3个1🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t12_放苹果🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t13_欢乐打飞机🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t14_删字母🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t15_最小数位和🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t16_统计次数🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t17_相近分解🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t18_对折次数🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t19_电扇控制🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t20_最大差🧡🧡
- 问题描述
- 思路
- 代码
- 🧡🧡t21_最尖位置🧡🧡
- 问题描述
- 思路
- 代码
后两期题目解析👇
15届蓝桥杯第二期模拟赛题单详细解析
15届蓝桥杯第三期模拟赛题单详细解析
🧡🧡t1_字母数🧡🧡
问题描述
请找到一个大于2022的最小数,这个数转换成十六进制之后,所有的数位(不含前导0)都为字母(A到F)。
这是一道结果填空的题,你只需要算出结果后提交即可。
思路
可利用Integer.toHexString方法转为二进制串,然后循环检查即可。
代码
public class Main {
public static boolean check(char[] ch) {
for (char c : ch) {
if (c >= '0' && c <= '9')
return false;
}
return true;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int x = 2022;
while (true) {
String hexString = Integer.toHexString(x);
char[] ch = hexString.toCharArray();
if (check(ch)) {
System.out.println(x);
break;
}
x++;
}
}
}
🧡🧡t2_大乘积🧡🧡
问题描述
小蓝有30个数,分别为:99, 22, 51, 63, 72, 61, 20, 88, 40, 21, 63, 30, 11, 18, 99, 12, 93, 16, 7, 53, 64, 9, 28, 84, 34, 96, 52, 82, 51, 77 。
小蓝可以在这些数中取出两个序号不同的数,共有 30×29/2=435种取法。
请问这435种取法中,有多少种取法取出的两个数的乘积大于等于2022。
这是一道结果填空的题,你只需要算出结果后提交即可。
思路
数据较小,才30个,直接两个for循环暴力枚举即可。
代码
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = { 99, 22, 51, 63, 72, 61, 20, 88, 40, 21, 63, 30, 11, 18, 99, 12, 93, 16, 7, 53, 64, 9, 28, 84, 34,
96, 52, 82, 51, 77 };
long res = 0;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] * arr[j] >= 2022)
res++;
}
}
System.out.println(res);
}
}
🧡🧡t3_星期几🧡🧡
问题描述
给定一天是一周中的哪天,请问n天后是一周中的哪天?
输入:
输入第一行包含一个整数n,表示给定的天是一周中的哪天,w为1到6分别表示周一到周六,w为7表示周日。
第二行包含一个整数n
输出:
输出一行包含一个整数,表示n天后是一周中的哪天,1到6分别表示周一到周六,7表示周日。
思路
简单计算,一点点小学数学
代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
int w = scanner.nextInt();
int n = scanner.nextInt();
int ans = (w + n % 7) % 7;
if (ans == 0)
System.out.println(7);
else
System.out.println(ans);
}
}
🧡🧡t4_列名🧡🧡
问题描述
在 Excel 中,列的名称使用英文字母的组合。前26列用一个字母,依次为A到Z,接下来 26×26 列使用两个字母的组合,依次为AA到ZZ 。
请问第2022列的名称是什么?
这是一道结果填空的题,你只需要算出结果后提交即可。
思路
可以依次按个数遍历,我选择采用递归搜索出A到Z的字母组合,然后统计即可。
代码
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Deque;
import java.util.List;
public class Main {
public static List<List<Character>> path = new ArrayList<>();
public static Deque<Character> sub = new ArrayDeque<>();
public static void dfs(int deep) {
path.add(new ArrayList<>(sub));
if (deep == 3) {
return;
}
for (char ch = 'A'; ch <= 'Z'; ch++) {
sub.addLast(ch);
dfs(deep + 1);
sub.removeLast();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
dfs(0);
path.remove(0); // 去除首个空集
// System.out.println(path.size());
path.sort(new Comparator<List<Character>>() {
public int compare(List<Character> list1, List<Character> list2) {
return list1.size() - list2.size();
}
});
// for (List sub : path) {
// System.out.println(sub.toString());
// }
for (int i = 0; i < path.size(); i++) {
if (i == 2022 - 1) {
for (char c : path.get(i)) {
System.out.print(c);
}
}
}
}
}
🧡🧡t5_清理水域🧡🧡
问题描述
小蓝有一个 n x m 大小的矩形水域,小蓝将这个水域划分为 n 行 m 列,行数从 1 到 n 标号,列数从 1 到 m 标号。每行和每列的宽度都是单位 1 。
现在,这个水域长满了水草,小蓝要清理水草。
每次,小蓝可以清理一块矩形的区域,从第 r1 行(含)到第 行 r2(含)的第 c1 列(含)到 c2 列(含)。
经过一段时间清理后,请问还有多少地方没有被清理过。
输入:
输入第一行包含两个整数 n,m,用一个空格分隔
第二行包含一个整数 t,表示清理的次数。
接下来 t 行,每行四个整数r1,c1,r2,c2 ,相邻整数之间用一个空格分隔,表示一次清理。请注意输入的顺序。
输出:
输出一行包含一个整数,表示没有被清理过的面积。
样例1
2 3
2
1 1 1 3
1 2 2 2
2
样例2
30 20
2
5 5 10 15
6 7 15 9
519
思路
考虑n、m、t只在100以内,最多10^6,因此可以暴力枚举每次矩形清洁。用一个状态数组st表示是否被清洁,清洁置为true
代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
public class Main {
private static BufferedReader bin = new BufferedReader(new InputStreamReader(System.in));
private static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
public static boolean[][] st = new boolean[105][105];
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String[] lineStrings1 = bin.readLine().split(" ");
int n = Integer.parseInt(lineStrings1[0]);
int m = Integer.parseInt(lineStrings1[1]);
int t = Integer.parseInt(bin.readLine());
while (t-- > 0) {
String[] tmpStrings = bin.readLine().split(" ");
int r1 = Integer.parseInt(tmpStrings[0]) - 1;
int c1 = Integer.parseInt(tmpStrings[1]) - 1;
int r2 = Integer.parseInt(tmpStrings[2]) - 1;
int c2 = Integer.parseInt(tmpStrings[3]) - 1;
for (int i = r1; i <= r2; i++) { // clean
for (int j = c1; j <= c2; j++) {
st[i][j] = true;
}
}
}
int ans = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (!st[i][j])
ans++;
}
}
out.print(ans);
out.flush();
}
}
🧡🧡t6_最大连通🧡🧡
问题描述
小蓝有一个 30 行 60 列的数字矩阵,矩阵中的每个数都是 0 或 1 。
110010000011111110101001001001101010111011011011101001111110
010000000001010001101100000010010110001111100010101100011110
001011101000100011111111111010000010010101010111001000010100
101100001101011101101011011001000110111111010000000110110000
010101100100010000111000100111100110001110111101010011001011
010011011010011110111101111001001001010111110001101000100011
101001011000110100001101011000000110110110100100110111101011
101111000000101000111001100010110000100110001001000101011001
001110111010001011110000001111100001010101001110011010101110
001010101000110001011111001010111111100110000011011111101010
011111100011001110100101001011110011000101011000100111001011
011010001101011110011011111010111110010100101000110111010110
001110000111100100101110001011101010001100010111110111011011
111100001000001100010110101100111001001111100100110000001101
001110010000000111011110000011000010101000111000000110101101
100100011101011111001101001010011111110010111101000010000111
110010100110101100001101111101010011000110101100000110001010
110101101100001110000100010001001010100010110100100001000011
100100000100001101010101001101000101101000000101111110001010
101101011010101000111110110000110100000010011111111100110010
101111000100000100011000010001011111001010010001010110001010
001010001110101010000100010011101001010101101101010111100101
001111110000101100010111111100000100101010000001011101100001
101011110010000010010110000100001010011111100011011000110010
011110010100011101100101111101000001011100001011010001110011
000101000101000010010010110111000010101111001101100110011100
100011100110011111000110011001111100001110110111001001000111
111011000110001000110111011001011110010010010110101000011111
011110011110110110011011001011010000100100101010110000010011
010011110011100101010101111010001001001111101111101110011101
如果从一个标为 1 的位置可以通过上下左右走到另一个标为 1 的位置,则称两个位置连通。与某一个标为 1 的位置连通的所有位置(包括自己)组成一个连通分块。
请问矩阵中最大的连通分块有多大?
这是一道结果填空的题,你只需要算出结果后提交即可。
思路
利用递归搜索
1.每个节点的终止搜索条件是遇到字符‘0’
2.首节点生长操作为4个方向,后续子节点通过used状态数组来决定还有哪些方向可以搜索
3.搜索到字符‘1’节点,则统计+1
4.遍历所有可能的首节点位置,记录各个搜索统计数的最大值
代码
import java.util.Scanner;
public class Main {
public static char[][] grid = new char[31][61];
public static boolean[][] used = new boolean[31][61];
public static int[] dx = { -1, 1, 0, 0 };
public static int[] dy = { 0, 0, -1, 1 };
public static int connect = 0;
public static int cnt = 0;
public static void dfs(int x, int y) {
if (grid[x][y] == '0') {
return;
}
used[x][y] = true;
cnt++;
for (int i = 0; i < 4; i++) {
int tx = x + dx[i], ty = y + dy[i];
if (tx < 1 || tx > 30 || ty < 1 || ty > 60)
continue;
if (used[tx][ty])
continue;
dfs(tx, ty);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
// Scanner sc = new Scanner(System.in);
// for (int i = 1; i <= 30; i++) {
// String s = sc.nextLine();
// for (int j = 1; j <= 60; j++) {
// grid[i][j] = s.charAt(j - 1);
// }
// }
// for (int i = 1; i <= 30; i++) {
// for (int j = 1; j <= 60; j++) {
// cnt = 0;
// dfs(i, j);
// connect = Math.max(connect, cnt);
// }
// }
// System.out.println(connect);
System.out.println(148);
}
}
🧡🧡t7_信号覆盖🧡🧡
问题描述
小蓝负责一块区域的信号塔安装,整块区域是一个长方形区域,建立坐标轴后,西南角坐标为(0,0) , 东南角坐标为 (W,0), 西北角坐标为(0,H) , 东北角坐标为(W,H) 。其中 W, H 都是整数。
他在 n 个位置设置了信号塔,每个信号塔可以覆盖以自己为圆心,半径为 R 的圆形(包括边缘)。
为了对信号覆盖的情况进行检查,小蓝打算在区域内的所有横纵坐标为整数的点进行测试,检查信号状态。其中横坐标范围为 0 到 W,纵坐标范围为 0 到 H,总共测试 (W+1) x (H+1) 个点。
给定信号塔的位置,请问这 (W+1) x (H+1) 个点中有多少个点被信号覆盖。
输入:
输入第一行包含四个整数 W, H, n, R,相邻整数之间使用一个空格分隔。接下来 n 行,每行包含两个整数 x,y,表示一个信号塔的坐标。信号塔可能重合,表示两个信号发射器装在了同一个位置。
输出:
输出一行包含一个整数,表示答案。
样例1
10 10 2 5
0 0
7 0
57
思路
同t5_清理水域类似,数据范围100100100,考虑直接暴力,根据坐标距离公式改变状态数组st即可。
代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
public class Main {
private static BufferedReader bin = new BufferedReader(new InputStreamReader(System.in));
private static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
public static boolean[][] st = new boolean[105][105];
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String[] lineStrings = bin.readLine().split(" ");
int W = Integer.parseInt(lineStrings[0]);
int H = Integer.parseInt(lineStrings[1]);
int n = Integer.parseInt(lineStrings[2]);
int R = Integer.parseInt(lineStrings[3]);
while (n-- > 0) {
String[] tmpStrings = bin.readLine().split(" ");
int x = Integer.parseInt(tmpStrings[0]);
int y = Integer.parseInt(tmpStrings[1]);
for (int i = 0; i <= W; i++) {
for (int j = 0; j <= H; j++) {
if (Math.sqrt((i - x) * (i - x) + (j - y) * (j - y)) <= R)
st[i][j] = true;
}
}
}
int ans = 0;
for (int i = 0; i <= W; i++) {
for (int j = 0; j <= H; j++) {
if (st[i][j])
ans++;
}
}
out.print(ans);
out.flush();
}
}
🧡🧡t8_附近最小🧡🧡
问题描述
小蓝有一个序列 a[1] a[2] a[3] … a[n]。
给定一个正整数 k ,请问对于每一个 1到 n 之间的序号 i,a[i-k], a[i-k+1], … a[i+k] 这 2k+1 个数中的最小值是多少?
当某个下标超过 1 到 n的范围时,数不存在,求最小值时只取存在的那些值。
输入:
输入的第一行包含一整数 n
第二行包含 n,分别表示 a[1] a[2] a[3] … a[n]
第三行包含一个整数 k
输出:
输出一行,包含 n 个整数,分别表示对于每个序号求得的最小值。
样例:
5
5 2 7 4 3
1
2 2 2 3 3
思路
方案1:两重循环暴力枚举,外层循环遍历1-n,内层循环遍历2*k+1个数,求其最小值。若k>10000,则 1 0 6 ∗ 1 0 4 10^ 6 * 10^4 106∗104容易超时。
方案2:将两层循环用线段树优化为一层循环,每次只需要求出左右端点,代入线段树的query即可返回最小值。
代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
private static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
private static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
private static int ini() throws IOException {
st.nextToken();
return (int) st.nval;
}
public static class Node {
int l, r;
int minv;
public Node(int l, int r, int minv) {
this.l = l;
this.r = r;
this.minv = minv;
}
}
public static final int N = 1000010;
public static int n, k;
public static Node[] tr = new Node[N * 4];
public static int[] arr = new int[N];
public static void pushup(int u) {
tr[u].minv = Math.min(tr[u * 2].minv, tr[u * 2 + 1].minv);
}
public static void build(int u, int l, int r) {
if (l == r) {
tr[u] = new Node(l, r, arr[l]);
return;
}
tr[u] = new Node(l, r, Integer.MAX_VALUE);
int mid = l + r >> 1;
build(u * 2, l, mid);
build(u * 2 + 1, mid + 1, r);
pushup(u);
}
public static int query(int u, int left, int right) {
if (tr[u].l >= left && tr[u].r <= right) {
return tr[u].minv;
}
int mid = tr[u].l + tr[u].r >> 1;
int tmp = Integer.MAX_VALUE;
if (left <= mid)
tmp = Math.min(tmp, query(u * 2, left, right));
if (right > mid)
tmp = Math.min(tmp, query(u * 2 + 1, left, right));
return tmp;
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
n = ini();
for (int i = 1; i <= n; i++)
arr[i] = ini();
k = ini();
build(1, 1, n);
for (int i = 1; i <= n; i++) {
int left = i - k;
int right = i + k;
if (left < 1)
left = 1;
if (right > n)
right = n;
out.print(query(1, left, right) + " ");
}
out.flush();
}
}
🧡🧡t9_特殊日期🧡🧡
问题描述
记一个日期为 yy 年 mm 月 dd 日,统计从 2000 年 1 月 1 日(含)到 2000000 年 1 月 1 日(含),有多少个日期满足年份 yy 是月份 mm 的倍数,同时也是 dd 的倍数。
这是一道结果填空的题,你只需要算出结果后提交即可。
思路
考虑直接从20000101= 1 0 7 10^{7} 107遍历到20000000101 = 1 0 10 10^{10} 1010,c++1秒大概运行 1 0 9 10^{9} 109,java稍慢,因此时间估计上1分钟内肯定能出答案。
每次通过除法运算和模运算提取出年月日,判断是否符合基本日期,然后再验证是否为倍数关系。
代码
public class Main {
public static int[] mon_day = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
public static boolean check(long y, long m, long d) {
mon_day[2] = (y % 4 == 0 && y % 100 != 0) || y % 400 == 0 ? 29 : 28;
if (!(m >= 1 && m <= 12))
return false;
if (!(d >= 1 && d <= mon_day[(int) m]))
return false;
return true;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
long ans = 0;
// for (long date = 20000101; date <= 20000000101L; date++) {
// long y = date / 10000;
// long m = date % 10000 / 100;
// long d = date % 100;
// if (check(y, m, d)) {
// if (y % m == 0 && y % d == 0)
// ans++;
// }
// }
// System.out.println(ans);
System.out.println(35813063);
}
}
🧡🧡t10_第三小🧡🧡
问题描述
给定一个序列 a[1] a[2] a[3] … a[n] ,对于3<=i<=n ,请求出前 i 个数中的第 3 小值。
输入:
输入的第一行包含一个整数 n ,表示序列的长度。
第二行包含 n 个整数,相邻的整数之间使用一个空格分隔,表示给定的序列。
输出:
输出一行包含 n-2 个整数,相邻两个数之间使用一个空格分隔,第 i 个整数表示 a[1] a[2] a[3] … a[i+2] 中的第 3 小值。
样例:
9
9 9 8 2 4 4 3 5 3
9 9 8 4 4 4 3
思路
方案1:两层循环暴力枚举,外层遍历1-n,内层遍历当前i个数,但是 1 0 6 ∗ 1 0 6 10^6*10^6 106∗106会超时
方案2:考虑优化内层循环,例如:3 2 2 4 5 6 7 8,对于前3个数的第3小值是3,对于前4个数的第3小值也是3,对于前5个数的第3小值也是3…
可以发现,只要从第4个数开始,若都大于前3个数的第3小值(即前3个数的最大值),则前n个数的第3小值不会变化(仍然是前3个数的最大值)。
若从第4个数开始,小于前3个数的任意一个数,则进行相应更新即可。
这样,时间复杂度优化到 1 0 6 10^6 106。
代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;
public class Main {
private static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
private static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
private static int ini() throws IOException {
st.nextToken();
return (int) st.nval;
}
public static int[] three = new int[3];
public static int[] arr;
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
int n = ini();
arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = ini();
}
if (n <= 3) {
Arrays.sort(arr);
out.print(arr[n - 1]);
} else {
three[0] = arr[0];
three[1] = arr[1];
three[2] = arr[2];
Arrays.sort(three);
// out.print(Arrays.toString(three));
out.print(three[2] + " ");
for (int i = 3; i < n; i++) {
// out.print(arr[i] + ": ");
if (arr[i] < three[2] && arr[i] >= three[1]) {
three[2] = arr[i];
} else if (arr[i] < three[1] && arr[i] >= three[0]) {
three[2] = three[1];
three[1] = arr[i];
} else if (arr[i] < three[0]) {
three[2] = three[1];
three[1] = three[0];
three[0] = arr[i];
}
// out.println(Arrays.toString(three));
out.print(three[2] + " ");
}
}
out.flush();
}
}
🧡🧡t11_3个1🧡🧡
问题描述
有的数转换为二进制之后,正好有 3 个数位为 1。例如 7转换为二进制为111 ,有 3 个数位为 1 ;又如 11 转换为二进制为 1011,有 3 个数位为 1。满足条件的前几个数依次为:7,11,13,14,19,21, ……请问,第 23 个满足条件的数是多少?
思路
利用Integer.toBinaryString(i)转为二进制字符串,遍历这个字符串,统计1的个数即可。
代码
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
int ans = 0;
for (int i = 1; i <= 10000; i++) {
String s = Integer.toBinaryString(i);
int cnt = 0;
for (int j = 0; j < s.length(); j++) {
if (s.charAt(j) == '1')
cnt++;
}
if (cnt == 3)
ans++;
// System.out.println(ans + " " + i);
if (ans == 23) {
System.out.println(i);
break;
}
}
}
}
🧡🧡t12_放苹果🧡🧡
问题描述
小蓝家的苹果今年丰收了,总共收获了 2023 个苹果。小蓝要把苹果装箱,每个箱子有 3 层,每层可以放 3 行,每行放 4 个苹果。请问小蓝可以将自己家的苹果装满多少箱?请注意多余的不够一箱的苹果不能算一箱。
这是一道结果填空的题,你只需要算出结果后提交即可。
思路
过于简单,数学题。。。。
代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
System.out.println(2023 / 36);
}
}
🧡🧡t13_欢乐打飞机🧡🧡
问题描述
小王在开完飞机后还是觉得不过瘾,认为会开飞机并不值得吹捧,如果能将对手的飞机摧毁才是真的本事!
小张看到小王无法按捺住激动的心灵,于是给他的飞机安装了一个 “无限导弹发射器”。
小王只要瞄准了某架飞机,每按下一次发射键,就可以扣除飞机的一点生命值,一心一意的小王只要开始打了某架飞机,就会把这架飞机彻底摧毁,且摧毁之前不会再打其他飞机。
太空飞机场是一个神奇的地方,当第 i 架飞机被摧毁时,剩余飞机(被摧毁的除外)会自动变更其生命值,其中第 map[i][j] 架飞机变更为 ,这课打乱了小王的射击节奏。
小王为了展示自己的发射能力,计划先打生命值低的飞机,再逐步打击生命值高的飞机,即后打击飞机的生命值必定大于等于前打击飞机的生命值。
小王必须从第一架飞机开始(第一架飞机生命值固定为 0),请问小王最多可以击毁多少架飞机?
输入:
输入数据是一个哈希 Map,内置了一个二维数组,同学们可以通过i,加 键获取 map[i][j] 的数据。 map[i][j] 的数值代表击毁第 i 架飞机后,第 j 架飞机变更后的生命值上限,其中 map[i][j] 固定为 0,因为第 i 架飞机被摧毁后,再设置大于 0 的生命值没有意义。
同学们可以认为小王是从击毁第 1 架飞机后开始的,第 1 架飞机的生命值固定为 0。
输出:
题目需要输出一个数x ,x是小王采取后打击飞机的生命值必定大于等于前打击飞机的生命值的计划,最多可击毁的飞机数量。
样例1:
0 7 8
1 0 2
3 6 0
小王打掉第一架飞机后,剩余飞机的情况为:X 7 8(X代表已被摧毁)。
接着根据先易后难的思路,先打第二架,剩余飞机情况为:X X 2,其中 2 取值为数组 map[2][3],即摧毁第二架飞机后,第三架飞机变更的生命值。
因为第三架飞机的生命值 2 小于 上一架摧毁的 7,所以不能再摧毁,所以答案为 2。
样例2:
0 4 1 6
0 0 7 7
3 5 0 7
3 6 1 0
小王打掉第一架飞机后,剩余飞机的情况为:X 4 1 6。
接着摧毁第三架飞机,剩余飞机的情况为:X 5 X 7,其中 5 来自 map[3][2],7 来自 map[3][4]。即摧毁第 i 架飞机后 第 j 架飞机的生命值。
接着摧毁第二架飞机,剩余飞机的情况为:X X X 7,其中 7 来自 map[2][4]。
最后摧毁第四架飞机,全部飞机被摧毁,所以答案为 4。
思路
通过递归枚举多种排列方案,同时根据下一个节点飞机生命值是否大于等于当前节点飞机生命值来决定节点之间的扩展,答案就是要寻找这样的树的最深深度。
代码
import java.util.Scanner;
public class Main {
public static final int N = 1000;
public static int n;
public static boolean[] killed = new boolean[N];
public static int[][] blood = new int[N][N];
public static int ans = Integer.MIN_VALUE;
public static void dfs(int last, int now, int deep) {
ans = Math.max(ans, deep);
for (int j = 1; j <= n; j++) {
if (killed[j])
continue;
if (blood[now][j] < blood[last][now])
continue;
killed[j] = true;
dfs(now, j, deep + 1);
killed[j] = false;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
blood[i][j] = sc.nextInt();
}
}
killed[1] = true;
dfs(1, 1, 1);
System.out.println(ans);
}
}
🧡🧡t14_删字母🧡🧡
问题描述
给定一个由大写字母组成的长度为 n 的字符串,请在字符串中删除 m 个字符,使得剩下的字符串的字典序最小。
输入:
输入的第一行包含两个整数n,m ,用一个空格分隔。
第二行包含一个长度为 n 的字符串。
输出:
输出一行包含一个长为 n-m 的字符串,表示答案。
样例:
7 3
LANQIAO
AIAO
思路
贪心思想:从前往后遍历字符串,保证每次删除一个字母时,当前字符串字典序最小,那么遍历完所有字符串后,删除m个字母后的字符串即为答案。
代码
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static List<Character> list = new ArrayList<>();
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
String s = sc.next();
for (int i = 0; i < s.length(); i++) {
while (!list.isEmpty() && m > 0 && s.charAt(i) < list.get(list.size() - 1)) {
m--;
list.remove(list.size() - 1);
}
list.add(s.charAt(i));
// System.out.println(list.toString());
}
for (char c : list) {
System.out.print(c);
}
}
}
🧡🧡t15_最小数位和🧡🧡
问题描述
一个数的数位和是指这个数各个数位上的数字之和。例如 2023 的数位和是 2+0+2+3=7。对于以下这些数( 8行,每行 8 个,共 64 个),请问数位和最小的数是多少?(如果有多个,请回答出现最早的那个)
454771 329157 801601 580793 755604 931703 529875 361797
604358 529564 574776 821517 195563 688516 223321 607845
284772 603562 543328 707484 533688 380468 233733 257995
896582 670074 912386 702393 722092 834842 126346 606526
376981 910643 413754 945725 817853 651778 350775 676550
316935 487808 939526 900568 423326 298936 927671 539773
136326 717022 886675 466684 436470 558644 267231 902422
743580 857864 529622 320921 595409 486860 951114 558787
这是一道结果填空的题,你只需要算出结果后提交即可。
思路
利用除运算和模运算取出一个数的每一位,暴力枚举即可。
代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int minv = Integer.MAX_VALUE;
int res = 0;
for (int i = 1; i <= 8; i++) {
for (int j = 1; j <= 8; j++) {
int sum = 0;
int x = sc.nextInt();
int tmp = x;
while (tmp > 0) {
sum += tmp % 10;
tmp /= 10;
}
if (minv > sum) {
minv = sum;
res = x;
}
}
}
System.out.println(res);
}
}
🧡🧡t16_统计次数🧡🧡
问题描述
给定一个仅包含数字字符的字符串,请统计一下这个字符串中出现了多少个0 、多少个 1 、……、多少个 9
输入:
输入一行包含一个字符串,仅有数字字符组成。
输出:
输出一行包括10个整数,相邻整数之间使用一个空格分隔,分别表示0到出现的次数。
样例:
123455
0 1 1 1 1 2 0 0 0 0
思路
数据量只有10000,适合暴力。
建立一个数组arr【x】= cnt,表示x出现了cnt次。
同时注意char数字转为int数字的方法:ch-‘0’
代码
import java.util.Scanner;
public class Main {
public static int[] arr = new int[10]; // 0-9
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
for (int i = 0; i < s.length(); i++) {
int x = (int) s.charAt(i) - '0';
arr[x]++;
}
for (int num : arr) {
System.out.print(num + " ");
}
}
}
🧡🧡t17_相近分解🧡🧡
问题描述
如果一个正整数 n 可以表示为三个整数的乘积,且这三个数的差都不超过 2 ,则称 n 可以进行相近分解。即 n可以写为 abc 的形式,而且 |a-b|<=2,|b-c|<=2,|a-c|<=2。请问第 23 小的可以进行相近分解的正整数是多少?
这是一道结果填空的题,你只需要算出结果后提交即可。
思路
三层循环暴力枚举a、b、c(小注意点:如:1,1,2和1,2,1,虽然顺序不一样,但是依据题意应该是同一组a、b、c。因此为确保不重复枚举,for循环中可让a<=b<=c即可。
代码
public class Main {
public static int cnt = 0;
public static boolean check(int n) {
for (int a = 1; a <= 30; a++) {
for (int b = a; b <= 30; b++) {
for (int c = b; c <= 30; c++) {
if (a * b * c == n) {
if (Math.abs(a - b) <= 2 && Math.abs(a - c) <= 2 && Math.abs(b - c) <= 2) {
// System.out.println(a + " " + b + " " + c);
return true;
}
}
}
}
}
return false;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int cnt = 0;
// 112 121?
for (int i = 1; i <= 10000; i++) {
if (check(i))
cnt++;
if (cnt == 23) {
System.out.println(i); // 120
break;
}
}
}
}
🧡🧡t18_对折次数🧡🧡
问题描述
小蓝有一根长度为 L 的绳子,每对折一次,长度变为原来的一半,请问对折多少次后长度不超过 1。
例如,当 L=6 时,对折一次长度为 3,对折两次长度为 1.5 ,对折 3 次长度为 0.75,所以 3 次后长度不超过 1.
输入:
输入一行包含一个整数 L
输出:
输出一行包含一个整数,表示答案。
样例1:
256
8
样例2:
257
9
思路
把L一直除2,统计次数即可。
题目不难,但是遇到了小坑:
样例输入:144115188075855873
标准输出:58
我的答案:57
原因:除到第57次是1.0000000000000000069388939039073 ,这个数是比1大的,但是double精度有限,所以认为其等于1。
解决:改用BigDecimal进行高精度,同时注意,用形如new BigDecimal(“1”)即用字符串来生成,用数字仍会出错。
代码
import java.math.BigDecimal;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
// =====input:144115188075855873 out:58=====
// double丢失精度
// double L = sc.nextDouble();
// int cnt = 0;
// while (L > 1) {
// cnt++;
// L = L / 2;
// System.out.println(L);
// }
// System.out.println(cnt);
// System.out.println(1.0000000000000000069388939039073 == 1);
// 高精度 ,注意最好用字符串来转换BigDecimal,而不是使用任何与double有关的类型:Double.toStirng、2.0等等
String inputString = sc.nextLine();
BigDecimal L = new BigDecimal(inputString);
int cnt = 0;
while (L.compareTo(new BigDecimal("1")) > 0) {
cnt++;
L = L.divide(new BigDecimal("2"));
}
System.out.println(cnt);
// System.out.println(new BigDecimal("1.0000000000000000069388939039073").equals(BigDecimal.valueOf(1)));
}
}
🧡🧡t19_电扇控制🧡🧡
问题描述
小蓝家的电扇有低、中、高三档,初始时电扇位于低档,当按一下电扇的调节按钮时,电扇变为中档,再按一下电扇变为高档,再按一下变为低档,依次循环。
从低档开始,小蓝连续按了 P 次调档按钮,请问电扇现在是哪一档?
例如,当 P=5 时,最终是高档。又如,当 P=10 时,最终是中档。
输入:
输入一行包含一个整数 P
输出:
如果最终是低档,输出小写英文字符串 low;如果最终是中档,输出小写英文字符串 mid;如果最终是高档,输出小写英文字符串 high
样例:
10
mid
思路
又是关于取模的数学问题。easy
代码
import java.util.Scanner;
public class Main {
public static String[] level = { "low", "mid", "high" };
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(level[n % 3]);
}
}
🧡🧡t20_最大差🧡🧡
问题描述
对于一个 n 行 m 列的矩阵,矩阵中的第 r 行第 c 列用二元组 (r,c) 表示。
两个位置 (a,b) 和 (c,d) 之间的距离为 |a-c|+|b-d|,即从一个位置到另一个位置需要走过的行数加上需要走过的列数。
给定以下 30 行 20 列的矩阵。
5137 8534 5597 3858 9242 7901 5735 4752 3590 6568 8481 1039 9940 9666 2950 1119 9391 7083 4625 8509
9661 6419 1115 2502 2663 5787 9553 7676 7508 3428 5698 1757 6048 8086 3091 1620 1277 1419 9534 5014
4125 9529 1679 9525 1896 2988 9763 3348 9366 1248 3699 7555 3167 9637 3632 1165 4143 8678 8590 2559
8822 8835 4322 5504 3759 4993 3402 4171 8027 4096 1933 7803 8034 2560 9801 7238 2611 9710 9350 2387
7413 7211 3107 5763 6372 2439 6668 1892 2076 5500 8264 2324 8747 4871 8962 2672 1398 3421 2508 2793
4965 9822 5995 3687 5007 1500 5033 1787 4380 1000 4069 6532 2023 3430 8036 7491 3960 6755 4173 1693
8836 8610 3057 5447 4001 7848 1081 6441 9940 8584 7272 5980 3735 8203 6889 4069 2760 3629 3819 3806
2389 9878 6163 3273 4565 9555 9764 4663 5197 5417 7669 6991 8089 6394 6961 8681 9700 3870 2243 5311
8103 7366 2394 7100 7594 3715 4593 9263 8125 8233 4523 2144 4814 2990 3657 4785 7583 8574 1335 8833
1654 8952 9522 1759 3219 3389 1600 5384 7865 1244 7198 2922 4883 7763 3163 5019 3593 2738 4405 2470
2246 6189 5809 5824 3465 5961 5751 1041 4460 2481 8948 4457 7853 6995 8558 4521 8908 9785 1926 3572
8302 2528 9940 4514 1389 5333 4862 9811 1070 4862 3095 1336 3409 7779 7709 7524 4195 2464 5806 3991
3414 8622 2139 4970 4211 1474 5610 8534 6228 5955 8105 7034 4600 8445 3055 2723 9615 5666 1291 6734
8046 5166 7040 8201 8825 5220 5867 3269 8799 5285 1705 3271 8660 1559 8889 9833 9800 3393 4002 3087
3339 3753 1699 3662 2975 6709 2931 6437 2750 6376 5119 1412 3806 3836 7429 6393 7661 7638 4959 9775
3681 5303 9472 3821 6692 1690 2170 7144 5132 2402 7483 3806 7831 1584 7894 8907 7029 4832 1675 4022
6622 6455 2206 5189 3874 2819 5304 3327 9723 8756 2253 4483 4005 2539 8246 1887 9571 8397 1067 4393
4981 5432 7097 5512 8146 3286 5150 1717 3912 9794 1291 9356 5867 2859 3969 8923 2909 1303 2068 4981
2557 8192 1391 3839 4577 4491 5678 1239 7734 3398 4216 5026 8964 6124 2710 2942 5702 6536 5959 4856
2886 3077 7358 7363 2826 2438 4590 2038 3370 1846 3942 7574 2209 8937 7393 9020 1991 6662 7878 1492
9613 8885 3620 7561 5913 9032 1954 3118 4377 9838 4629 5447 8313 5514 2398 3412 8243 6406 9272 5676
7911 3914 2760 4286 4813 8555 8563 2017 3425 2995 1248 7067 4201 6228 9655 5684 6665 6909 1411 5755
5997 5965 9264 9780 7407 9247 9805 9601 8513 8995 1489 4059 1781 8177 3152 5155 8927 1659 6585 5236
6428 5704 7820 5584 1575 6593 1564 7261 5638 7396 2609 3468 9662 1271 2100 2946 1778 5975 2019 1113
7034 8041 2660 4038 5845 9221 8186 4893 3771 6855 6367 7818 3739 3463 4011 9659 7323 9413 1709 8610
3254 5705 1228 1479 9546 4221 3147 1027 4088 5022 5140 1586 7300 7384 5697 8129 8667 7264 2299 9641
5907 5332 9787 3037 8998 3672 3474 8796 9104 7331 8321 3021 1439 5992 9253 8387 2895 7489 3219 1056
8717 8100 4183 2250 1804 5588 6799 9781 7428 1675 6452 5683 4139 1186 2513 8412 4823 8360 6859 8448
1584 8119 1764 1598 3958 6205 1970 7925 8173 1094 8456 8579 3657 6227 8868 2921 7962 4787 8786 9714
3495 3036 7617 8448 3219 1455 4797 8053 8208 9694 7293 4144 1244 7065 3223 7796 9161 4435 1928 8227
其中位置 (1,1) 和 (2,3) 的距离为 3,元素的值的差为4022 。请问,在以上矩阵中,位置的距离不超过 5 的元素的值的差最大是多少?
这是一道结果填空的题,你只需要算出结果后提交即可。
思路
类似BFS搜索,遍历每一个坐标,枚举出它走不超过5步能到达的坐标,用全局变量记录最值即可。
代码
import java.util.Scanner;
public class Main {
public static int[][] arr = new int[35][25];
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
for (int i = 1; i <= 30; i++) {
for (int j = 1; j <= 20; j++) {
arr[i][j] = sc.nextInt();
}
}
int maxv = Integer.MIN_VALUE;
for (int i = 1; i <= 30; i++) {
for (int j = 1; j <= 20; j++) {
for (int ty = -5; ty <= 5; ty++) {
for (int tx = -5; tx <= 5; tx++) {
int x = i + tx, y = j + ty;
if (x <= 0 || x >= 30 || y <= 0 || y >= 20)
continue;
if (Math.abs(x - i) + Math.abs(y - j) > 5)
continue;
maxv = Math.max(maxv, Math.abs(arr[i][j] - arr[x][y]));
}
}
}
}
System.out.println(maxv); // 8940
}
}
🧡🧡t21_最尖位置🧡🧡
问题描述
对于一个序列a[1] a[2] a[3] … a[n] ,如果 a[i] 满足 a[i] <a[i-1]且 a[i]<a[i+1],则称 i 位置尖的程度定为 (a[i-1] - a[i]) x (a[i+1] - a[i])。
给定一个序列,请找到一个尖的位置,这个位置尖的程度值最大。
输入:
输入的第一行包含一个整数 n ,表示序列的长度。
第二行包含 n 个整数,相邻的整数之间使用一个空格分隔,表示给定的序列。
输出一行包含一个整数,表示找到的最大的尖的程度值。如果不存在尖位置,输出 0
输出:
样例:
8
1 8 2 4 4 3 5 3
12
思路
数据范围较小,考虑暴力。定义一个全局变量max_ridge记录最值,同时再定义一个布尔变量flag,表示是否有尖位置。
代码
import java.util.Scanner;
public class Main {
public static int[] arr = new int[1010];
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 1; i <= n; i++) {
arr[i] = sc.nextInt();
}
boolean flag = true;
int max_ridge = -1;
for (int i = 2; i <= n - 1; i++) {
if (arr[i] < arr[i - 1] && arr[i] < arr[i + 1]) {
max_ridge = Math.max(max_ridge, (arr[i - 1] - arr[i]) * (arr[i + 1] - arr[i]));
flag = false;
}
}
if (flag)
System.out.println(0);
else
System.out.println(max_ridge);
}
}