76
突破口在于如果当前卡片的数量小于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;
}
}
}
不同的直线斜率或者截距必有一个不同,使用字符串来表示每条直线的斜率和截距,并存入集合当中。
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);
}
}
首先保存一下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;
}
}
}
首先初始化一个边集数组,初始化数组元素足够大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);
}
}
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);
}
}
1 1
2 1 3 '2' + 1 = 3 尽可能地增添比较大的砝码
3 1 3
4 1 3 1 + 3 = 4
5 1 3 9 ‘5’ + 1 + 3 = 9
...
13 1 3 9 1 + 3 + 9 = 13
14 1 3 9 27 '14' + 1 + 3 + 9 = 27
...
增加的砝码质量是之前的立方,砝码总重小于等于待测值时,停止
import java.util.Scanner;
/**
* @Description
* @Author:PrinceHan
* @CreateTime:2022/2/24 15:19
*/
public class G {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int n = 1;
int ans = 1;
int w = 1;
while (n < N) {
w *= 3;
ans++;
n += w;
}
System.out.println(ans);
}
}
一开始想着暴力解,结果超时了,这里参考了y总的思路,第十二届蓝桥杯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;
}
}
这道题还挺难的,我能想到的是用sort排,但是会超时,目前的解法还是根据y总的视频写出来的,大家可以看y总的视频 第十二届蓝桥杯C++ B组讲解,或者移步ACwing 双向排序,讲解都比较详细。
import java.util.Scanner;
/**
* @Description
* @Author:PrinceHan
* @CreateTime:2022/2/24 15:57
*/
public class Main {
static int N = 100010;
static pair[] stk = new pair[N];
static int[] ans = new int[N];
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
int top = 0;//初始化栈顶
int p, q;
for (int i = 0; i < m; i++) {
p = scanner.nextInt();
q = scanner.nextInt();
if (p == 0) {
//求出连续操作的最长前缀
while (top != 0 && stk[top].x == 0)
q = Math.max(q, stk[top--].y);
//删去所有比它小的前缀操作
while (top >= 2 && stk[top - 1].y <= q)
top -= 2;
//加上当前的前缀操作
stk[++top] = new pair(0, q);
} else if (top != 0) {
//求出连续操作的最长后缀
while (top != 0 && stk[top].x == 1)
q = Math.min(q, stk[top--].y);
//删去所有比它小的后缀操作
while (top >= 2 && stk[top - 1].y >= q)
top -= 2;
//加上当前的后缀操作
stk[++top] = new pair(1, q);
}
}
//k是递减变量,l为左边界,r为右边界
int k = n, l = 1, r = n;
//填数
for (int i = 1; i <= top; i++) {
if (stk[i].x == 0) {
//若为前缀操作,则(stk[i].y, r]不用操作,直接填数
while (r > stk[i].y && l <= r) ans[r--] = k--;
} else {
//若为后缀操作,则[l, stk[i].y)不用操作,直接填数
while (l < stk[i].y && l <= r) ans[l++] = k--;
}
if (l > r) break;//区间为空
}
//区间不为空
//若l < r, 表示中间还有些数没有填上,操作次数为奇数,则下一次操作为前缀操作
if (top % 2 == 1) {
while (l <= r) ans[l++] = k--;
} else {
while (l <= r) ans[r--] = k--;
}
for (int i = 1; i <= n; i++) {
System.out.printf("%d ", ans[i]);
}
}
static class pair {
int x, y;
pair(int x, int y) {
this.x = x;
this.y = y;
}
}
}