A.ASC
题解
76
B.卡片
题目分析
突破口在于如果当前卡片的数量小于0,则输出当前卡片表示的数的前一个数。若当前卡片足以表示一个数时,更新答案。
题解
3181
import java.util.Arrays;
/**
* @Description
* @Author:PrinceHan
* @CreateTime:2022/2/22 19:11
*/
public class Main {
public static void main(String[] args) {
int[] nums = new int[10];
int ans = -1;
Arrays.fill(nums, 2021);
for (int i = 0; i < 10000; i++) {
int tmp = i;
if (tmp == 0) nums[0]--;
else {
while (tmp != 0) {
if (nums[tmp % 10] < 0) {
System.out.println(ans - 1);
System.exit(0);
}
nums[tmp % 10]--;
tmp /= 10;
}
}
ans = i;
}
}
}
C.直线
题目分析
不同的直线斜率或者截距必有一个不同,使用字符串来表示每条直线的斜率和截距,并存入集合当中。
题解
40257
import java.util.ArrayList;
import java.util.HashSet;
/**
* @Description
* @Author:PrinceHan
* @CreateTime:2022/2/22 19:44
*/
public class C {
static class Point {
int x, y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void main(String[] args) {
ArrayList<Point> points = new ArrayList<>();
HashSet<String> lines = new HashSet<>();
int m = 19;
int n = 20;
int ans = 0;
for (int i = 0; i <= 19; i++) {
for (int j = 0; j <= 20; j++) {
points.add(new Point(i, j));
}
}
for (int i = 0; i < points.size(); i++) {
for (int j = 0; j < points.size(); j++) {
int x1 = points.get(i).x, y1 = points.get(i).y;
int x2 = points.get(j).x, y2 = points.get(j).y;
if (x1 == x2 && y1 == y2) continue;
if (x1 == x2) {
lines.add("x =" + x1);//考虑斜率不存在时的情况
} else if (y1 == y2) {
lines.add("y =" + y1);
} else {
int dx = x2 - x1;
int dy = y2 - y1;
int gcd1 = gcd(dx, dy);
int gcd2 = gcd(y1 * dx - x1 * dy, dx);
lines.add("k = " + dy / gcd1 + "/" + dx / gcd1 + " d = " + (y1 * dx - x1 * dy) / gcd2 + "/" + dx / gcd2);//化简斜率和截距
}
}
}
for (String e : lines) {
System.out.println(e);
}
System.out.println(lines.size());
}
static int gcd(int m, int n) {
return m % n == 0 ? n : gcd(n, m % n);
}
}
D.货物摆放
题目分析
首先保存一下2021041820210418的所有因数,只需遍历到该数的平方根为止,可以运行的更快。这个题可以用全排列的方法来做,选择三个因数进行全排列。
题解
2430
import java.util.ArrayList;
import java.util.stream.Collectors;
/**
* @Description
* @Author:PrinceHan
* @CreateTime:2022/2/22 20:24
*/
public class D {
static int ans;
static long n = 2021041820210418l;
static long[] nums = new long[10];
static ArrayList<Long> longs = new ArrayList<>();
public static void main(String[] args) {
for (long i = 1; i * i <= n; i++) {
if (n % i == 0) {
longs.add(i);
longs.add(n / i);
}
}
longs = (ArrayList<Long>) longs.stream().distinct().collect(Collectors.toList());//去重
dfs(0, 1);
System.out.println(ans);
}
static void dfs(int a, long now) {
if (a == 3) {
if (now == n) {
ans++;
}
return;
}
for (int i = 0; i < longs.size(); i++) {
nums[a] = longs.get(i);
dfs(a + 1, now * longs.get(i));
nums[a] = 0;
}
}
}
E.路径
题目分析
首先初始化一个边集数组,初始化数组元素足够大Integer.MAX_VALUE
,接着根据要求来给各顶点连边,并用路径场长度更新边集数组,最后用Floyd算法计算最短路径。
题解
10266837
import java.util.Arrays;
/**
* @Description
* @Author:PrinceHan
* @CreateTime:2022/2/23 18:03
*/
public class E {
static long[][] edge = new long[2100][2100];
public static void main(String[] args) {
for (int i = 1; i <= 2021; i++) {
Arrays.fill(edge[i], Integer.MAX_VALUE);//初始化
}
for (int i = 1; i <= 2021; i++) {
for (int j = i + 1; j <= i + 21 && j <= 2021; j++) {
int gcd = gcd(i, j);
edge[i][j] = i * j / gcd;//最小公倍数
edge[j][i] = edge[i][j];
}
}
for (int i = 1; i <= 2021; i++) {
for (int j = 1; j <= 2021; j++) {
for (int k = 1; k <= 2021; k++) {
if (edge[j][k] > edge[j][i] + edge[i][k])
edge[j][k] = edge[j][i] + edge[i][k];
}
}
}
System.out.println(edge[1][2021]);
}
static int gcd(int m, int n) {
return m % n == 0 ? n : gcd(n, m % n);
}
}
E.时间显示
题解
import java.util.Scanner;
/**
* @Description
* @Author:PrinceHan
* @CreateTime:2022/2/23 20:45
*/
public class F {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long l = scanner.nextLong();
l /= 1000;
l %= 86400;
long h = l / 3600;
l %= 3600;
long m = l / 60;
long s = l % 60;
System.out.printf("%02d:%02d:%02d", h, m, s);
}
}
G.最少砝码
H.杨辉三角形
题目分析
一开始想着暴力解,结果超时了,这里参考了大雪菜的思路,第十二届蓝桥杯C++ B组讲解,思路比较新颖。
题解
import java.util.Scanner;
/**
* @Description
* @Author:PrinceHan
* @CreateTime:2022/2/23 22:21
*/
public class H {
static long n;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextLong();
for (int k = 16; ; k--) {
if (check(k)) break;
}
}
//求组合数
static long c(int a, int b) {
long res = 1;
for (int i = a, j = 1; j <= b; i--, j++) {
res = res * i / j;
if (res > n) return res;
}
return res;
}
//二分检查
static boolean check(int k) {
int l = 2 * k, r = (int) Math.max(n, l);
while (l < r) {
int mid = (l + r) / 2;
if (c(mid, k) >= n) r = mid;
else l = mid + 1;
}
if (c(r, k) != n) return false;
// C(r, k)的从0开始的顺序!
int loc = (r + 1) * r / 2 + k + 1;
System.out.println(loc);
return true;
}
}