2021/第十二届蓝桥杯省赛/Java-B
A. 字母
字母A的ASCLL码值表示为65,那么字母L转换成ASCLL码值是多少
输出答案: 76
B. 卡片
大量数字卡片每个都是数字
static class Solution {
static int card(int n) {
int[] cards = new int[10];
Arrays.fill(cards, n);
int num = 1;
out:
while (true) {
int temp = num;
while (temp != 0) {
cards[temp % 10]--;
if (cards[temp % 10] < 0)
break out;
temp /= 10;
}
num++;
}
return num - 1;
}
}
输出答案: 3181
C. 直线
在平面直角坐标系中,在平面内任意选取两个不同位置的点即可唯一决定一条直线。当多个不同位置的共线点存在时,则这些共线点中的任意两个不同位置的点所决定的直线必然是同一条特定的几何对象。
在平面上给出下列整点集合:{(x, y)|0 ≤ x < 2, 0 ≤ y < 3, x ∈ Z, y ∈ Z} ,即该集合中的横坐标取值范围为从0到1(包括端值),纵坐标取值范围为从0到2(包括端值),其中Z代表所有整数集。
经计算得知上述有限离散空间中的这些整点集合总共决定了11条互不相同的几何线条结构体。
类似地,在另一个离散空间{(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z} 中共有20×21=420个不同的有序坐标组合元素存在。问题:上述420个不同位置的空间格子节点总共决定了多少条互不重合的基本几何构造单元?
static class Solution {
static int lines(int n, int m) {
int[] X = new int[n];
int[] Y = new int[m];
for (int i = 0; i < n; i++) X[i] = i;
for (int i = 0; i < m; i++) Y[i] = i;
HashSet<Line> set = new HashSet<>();
HashSet<String> pruning = new HashSet<>();
//(x-x1)/(x2-x1) = (y-y1)/(y2-y1)
//(x-x1)*(y2-y1) = (y-y1)*(x2-x1)
//x*(y2-y1) - y*(x2-x1) + y1*(x2-x1) - x1*(y2-y1) = 0
//A = y2-y1, B = x2-x1, C = y1*(x2-x1)/(y2-y1) - x1*(y2-y1)
String s;
for (int x1 : X) {
for (int y1 : Y) {
for (int x2 : X) {
for (int y2 : Y) {
if (x2 == x1 && y2 == y1) continue;
if (y2 - y1 < 0) {
s = y1 + " " + y2 + " " + x1 + " " + x2;
if (pruning.contains(s)) continue;
set.add(new Line(-(y2 - y1), -(x2 - x1), -1.0 * (y1 * (x2 - x1) - x1 * (y2 - y1))));
} else {
s = y2 + " " + y1 + " " + x2 + " " + x1;
if (pruning.contains(s)) continue;
set.add(new Line(y2 - y1, x2 - x1, 1.0 * y1 * (x2 - x1) - x1 * (y2 - y1)));
}
pruning.add(s);
}
}
}
}
// for (Line line : set)
// System.out.println(line.a + " " + line.b + " " + line.c);
return set.size();
}
static class Line {
int a = 0, b = 0;
double c;
public Line(int a, int b, double c) {
if (a == 0) {// y = R
c /= b;
b = 1;
} else if (b == 0) {// x = R
c /= a;
a = 1;
} else {
int gcd = gcd(a, b);
a /= gcd;
b /= gcd;
c /= gcd;
}
this.a = a;
this.b = b;
this.c = c;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Line) {
Line line = (Line) obj;
return line.a == this.a && line.b == this.b && line.c == this.c;
}
return false;
}
@Override
public int hashCode() {
return 0x11;
}
int gcd(int a, int b) {
if (a < b) {
int temp = b;
b = a;
a = temp;
}
int temp;
while ((temp = a % b) != 0) {
a = b;
b = temp;
}
return b;
}
}
}
输出答案: 40****257 (48秒32)
D. 货物摆放
小蓝有一个超大的仓库,可以摆放很多货物。
现在,小蓝有 n 箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝
规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、
宽、高。
小蓝希望所有的货物最终摆成一个大的立方体。即在长、宽、高的方向上
分别堆 L、W、H 的货物,满足 n = L × W × H。
给定 n,请问有多少种堆放货物的方案满足要求。
例如,当 n = 4 时,有以下 6 种方案:1×1×4、1×2×2、1×4×1、2×1×2、 2 × 2 × 1、4 × 1 × 1。
请问,当 n = 2021041820210418 (注意有 16 位数字)时,总共有多少种
方案?
static class Solution {
static int cargo(long n) {//2021041820210418L
ArrayList<Long> cands = new ArrayList<>();//candidate nums
cands.add(n);
for (long i = 1; i <= sqrt(n) + 1; i++)
if (n % i == 0)
cands.add(i);
HashSet<String> res = new HashSet<>();
for (int i = 0; i < cands.size(); i++) {
for (int j = 0; j < cands.size(); j++) {
if ((n / cands.get(i)) % cands.get(j) == 0) {
long A = cands.get(i);
long B = cands.get(j);
long C = (n / cands.get(i)) / cands.get(j);
String a = A + "x" + B + "x" + C;
String e = A + "x" + C + "x" + B;
String c = C + "x" + B + "x" + A;
String d = C + "x" + A + "x" + B;
String b = B + "x" + A + "x" + C;
String f = B + "x" + C + "x" + A;
res.add(a);
res.add(b);
res.add(c);
res.add(d);
res.add(e);
res.add(f);
}
}
}
//for (String re : res) {
// System.out.println(re);
//}
return res.size();
}
}
输出答案: 2430
E. 路径
小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图
中的最短路径。
小蓝的图由 2021 个结点组成,依次编号 1 至 2021。
对于两个不同的结点 a, b,如果 a 和 b 的差的绝对值大于 21,则两个结点
之间没有边相连;如果 a 和 b 的差的绝对值小于等于 21,则两个点之间有一条
长度为 a 和 b 的最小公倍数的无向边相连。
例如:结点 1 和结点 23 之间没有边相连;结点 3 和结点 24 之间有一条无
向边,长度为 24;结点 15 和结点 25 之间有一条无向边,长度为 75。
请计算,结点 1 和结点 2021 之间的最短路径长度是多少。
static class Solution {
static Long shortestPath() {
return Bellman_Ford();
}
static Long Bellman_Ford() {
Map<Integer, Long> dist = new HashMap<>();
for (int i = 1; i <= 2021; i++) {
dist.put(i, Long.MAX_VALUE);
}
dist.put(1, 0L);
for (int i = 1; i <= 2021; i++) {
for (int j = -21; j <= 21; j++) {
int from = i;
int to = i + j;
if (to <= 2021 && to >= 1) {
long weight = lcm(from, to);
if (dist.get(to) > dist.get(from) + weight)
dist.put(to, dist.get(from) + weight);
}
}
}
return dist.get(2021);
}
static long lcm(int a, int b) {
if (a < b) {
int temp = a;
a = b;
b = temp;
}
return (long) a * b / gcd(a, b);
}
static int gcd(int a, int b) {
int temp;
while ((temp = a % b) != 0) {
a = b;
b = temp;
}
return b;
}
}
输出答案: 10266837
F. 时间显示
问题描述
输入格式
输出格式
样例输入 1
样例输出 1
样例输入 2
static class Solution {
static String time(String s) {
BigDecimal mills = new BigDecimal(s);//String length is 10^18
BigDecimal seconds = mills.divide(new BigDecimal(1000), 0, RoundingMode.FLOOR);//10^15
BigDecimal days = seconds.divide(new BigDecimal(60 * 60 * 24), 0, RoundingMode.FLOOR);//10^11
int Second = days.compareTo(BigDecimal.ONE) <= 0 ?
seconds.intValue() : seconds.divideAndRemainder(days)[1].intValue();//if days is not zero then calculate remainder
Calendar c = Calendar.getInstance();
//c.setTimeInMillis(0);
c.set(Calendar.HOUR, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, Second);
//SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
return format.format(c.getTime());
}
}
G. 最少砝码
问题描述
static class Solution {
static int countWeights(int maxWeight) {
return Base_3(maxWeight);
}
static int Base_3(int weight) {
int cnt = 1;
int base = 1;
int sum = 1;
while (sum < weight) {
sum += base * 3;
base *= 3;
cnt++;
}
return cnt;
}
}
H. 杨辉三角形
【问题描述】
下面的图形是著名的杨辉三角形:

样例输入
static class Solution {
// 1
// 1 1
// 1 2 1
// 1 3 3 1
// 1 4 6 4 1
// 1 5 10 10 5 1
// Cn0 Cn1 Cn2 ... Cnn
static int index(int n) {
memory = new HashMap<>();
BigDecimal target = new BigDecimal(n);
if (n == 1)
return 1;
int index = 2;
int rows = 2;
while (true) {
for (int i = 0; i <= rows; i++) {
index++;
if (i > rows / 2 + 1)
continue;
if (target.compareTo(C(rows, i)) == 0) {
return index + 1;
}
}
rows++;
}
}
static Map<String, BigDecimal> memory;
static BigDecimal C(int n, int k) {
String s1 = (n - 1) + "," + k;
String s2 = (n - 1) + "," + (k - 1);
String s3 = n + "," + k;
BigDecimal add;
if (k == 0 || k == n)
add = BigDecimal.ONE;
else {
BigDecimal a = memory.get(s1);
BigDecimal b = memory.get(s2);
if (a == null) a = BigDecimal.ONE;
if (b == null) b = BigDecimal.ONE;
add = a.add(b);
}
memory.put(s3, add);
return add;
}
}
I. 双向排序
问题描述
输入格式
输出格式
样例输入
样例输出
样例说明
static class Solution {
private static int[] ints;
public static String sort(int n, int op[][]) {
ints = new int[n + 1];
for (int i = 1; i <= n; i++) {
ints[i] = i;
}
for (int i = 0; i < op.length; i++) {
if (op[i][0] == 0)
quickSort(1, op[i][1] + 1, true);//desc
else
quickSort(op[i][1], ints.length, false);//asc
System.out.println(Arrays.toString(ints));
}
StringBuilder s = new StringBuilder("" + ints[1]);
for (int i = 2; i < ints.length; i++) {
s.append(" ").append(ints[i]);
}
return s.toString();
}
static void quickSort(int left, int right, boolean order) {
if (left < right) {
int boundary = left;
for (int i = left + 1; i < right; i++) {
if (ints[i] < ints[left] ^ order) {
swap(i, ++boundary);
}
}
swap(left, boundary);
quickSort(left, boundary, order);
quickSort(boundary + 1, right, order);
}
}
static void swap(int a, int b) {
int temp = ints[a];
ints[a] = ints[b];
ints[b] = temp;
}
}
J. 括号序列
问题描述
输入格式
输出格式
样例输入
样例输出
评测用例规模与约定
