第十二届蓝桥杯Java B组题解

A.ASC

第十二届蓝桥杯Java B组题解

题解

76

B.卡片

第十二届蓝桥杯Java 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.直线

第十二届蓝桥杯Java B组题解

题目分析

不同的直线斜率或者截距必有一个不同,使用字符串来表示每条直线的斜率和截距,并存入集合当中。

题解

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.货物摆放

第十二届蓝桥杯Java B组题解

题目分析

首先保存一下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.路径

第十二届蓝桥杯Java B组题解

题目分析

首先初始化一个边集数组,初始化数组元素足够大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.时间显示

第十二届蓝桥杯Java B组题解
第十二届蓝桥杯Java B组题解

题解

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.最少砝码

第十二届蓝桥杯Java B组题解
第十二届蓝桥杯Java B组题解

H.杨辉三角形

第十二届蓝桥杯Java B组题解
第十二届蓝桥杯Java B组题解

题目分析

一开始想着暴力解,结果超时了,这里参考了大雪菜的思路,第十二届蓝桥杯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;
    }
}

上一篇:R 语言案例


下一篇:Java笔记总结(九)---数组的拷贝