首页 > 编程语言 >第12届蓝桥杯JavaB组省赛

第12届蓝桥杯JavaB组省赛

时间:2023-01-11 21:44:53浏览次数:63  
标签:12 int long 蓝桥 ++ static now public 组省赛

第12届蓝桥杯JavaB组省赛

前言

用时及分数

自测开始时间:\(2023年1月11日 16:00\)

自测结束时间:\(2023年1月11日 18:05\)

自测用时:约 \(2\) 小时

最终得分:\(20(35)\)

PS:此处得分依据蓝桥杯官网OJ测得

题目情况

完成题目:\(ABC(F)\)

\(F\) 题提交时的类名未使用 \(Main\),不得分。

\(D\) 题暴力写法跑了 \(30\) 分钟没跑出来

因为干饭提前结束测试

\(E\) 最短路没学或者说忘了

感受

\(12\) 届的题目填空题居然有 \(5\) 道,\(13\) 届才 \(2\) 道

而且感觉 \(13\) 届比 \(12\) 届更偏向算法知识了

注意点

  • 提交时一定要注意类名等情况,或者建文件时就建多个 \(Main\)

  • 心态放平,时间很充裕

  • 实在写不出来正解,也尽量把暴力写出来

  • 一定要把题目都看完

  • 填空题提交之前一定要先对小数据进行测试

试题 A ASC

问题描述

已知大写字母 \(A\) 的 \(ASCII\) 码为 \(65\),请问大写字母 \(L\) 的 \(ASCII\) 码是多少?

答案为:\(76\)

Code

public class Main {
    public static void main(String[] args) {
        System.out.println((int) ('L'));//76
    }
}

试题 B 卡片

问题描述

小蓝有很多数字卡片,每张卡片上都是数字 \(0\) 到 \(9\)。

小蓝准备用这些卡片来拼一些数,他想从 \(1\) 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。

小蓝想知道自己能从 \(1\) 拼到多少。

例如,当小蓝有 \(30\) 张卡片,其中 \(0\) 到 \(9\) 各 \(3\) 张,则小蓝可以拼出 \(1\) 到 \(10\),但是拼 \(11\) 时卡片 \(1\) 已经只有一张了,不够拼出 11。

现在小蓝手里有 \(0\) 到 \(9\) 的卡片各 \(2021\) 张,共 \(20210\) 张,请问小蓝可以从 \(1\) 拼到多少?

提示:建议使用计算机编程解决问题。

答案为:\(3181\)

思路

一个数组记录当前对应类型的牌剩余多少张,每算一个数字就减去所需的牌数

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] arr = new int[10];
        Arrays.fill(arr, 2021);
        int now = 1;
        while (true) {
            int t = now;
            while (t != 0) {
                if (arr[t % 10] > 0) --arr[t % 10];
                else {
                    //这里要输出now-1,因为当前这个牌是拼不出来的!!!
                    System.out.println(now-1);//3181
                    return;
                }
                t /= 10;
            }
            ++now;
        }
    }
}

试题 C 直线

问题描述

在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。

给定平面上 \(2 × 3\) 个整点 \(\{(x, y)|0 ≤ x < 2, 0 ≤ y < 3, x ∈ Z, y ∈ Z\}\),即横坐标是 \(0\) 到 \(1\) (包含 \(0\) 和 \(1\)) 之间的整数、纵坐标是 \(0\) 到 \(2\) (包含 \(0\) 和 \(2\)) 之间的整数的点。这些点一共确定了 \(11\) 条不同的直线。

给定平面上 \(20 × 21\) 个整点 \(\{(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z\}\),即横坐标是 \(0\) 到 \(19\) (包含 \(0\) 和 \(19\)) 之间的整数、纵坐标是 \(0\) 到 \(20\) (包含 \(0\) 和 \(20\)) 之间的整数的点。请问这些点一共确定了多少条不同的直线。

答案为:\(40257\)

思路

既然是填空题,比赛的时候能暴力解就暴力解

既能很快的得到答案,也能减少出错的概率

具体思路见注释

import java.util.LinkedList;
import java.util.List;

public class Main {
    static class Point {
        public int x, y;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    static class Line {

        public Point A, B;

        public Line(Point A, Point B) {
            this.A = A;
            this.B = B;
        }
    }

    static List<Line> list = new LinkedList<>();

    //判断点是否在该直线上
    public static boolean checkPoint(Point p, Line l) {
        return (p.y - l.A.y) * (p.x - l.B.x) == (p.y - l.B.y) * (p.x - l.A.x);
    }

    //判断两条直线是否为同一条
    public static boolean checkLine(Line a, Line b) {
        //先判断斜率是否相等
        if ((a.B.y - a.A.y) * (b.B.x - b.A.x) != (b.B.y - b.A.y) * (a.B.x - a.A.x)) return false;
        //如果斜率相等再取直线上一点,是否在另一直线上
        return checkPoint(a.A, b);
    }

    //判断列表中是否存在该直线
    public static boolean check(Line a) {
        for (Line l : list) {
            if (checkLine(a, l)) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        final int X = 20, Y = 21;
        for (int x1 = 0; x1 < X; ++x1) {
            for (int y1 = 0; y1 < Y; ++y1) {
                Point a = new Point(x1, y1);
                for (int x2 = 0; x2 < X; ++x2) {
                    for (int y2 = 0; y2 < Y; ++y2) {
                        //如果两点重合则不选
                        if (x2 == x1 && y2 == y1) continue;
//                        System.out.printf("a=(%d,%d),b=(%d,%d)\n", x1, y1, x2, y2);
                        Point b = new Point(x2, y2);
                        Line l = new Line(a, b);
                        if (!check(l)) list.add(l);
                    }
                }
            }
        }
        System.out.println(list.size());//40257
    }
}

试题 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\) 位数字)时,总共有多少种方案?

提示:建议使用计算机编程解决问题。

答案为:\(2430\)

思路一

遍历第一个数 \(L\),如果是 \(n\) 的因子,说明当前数可取,然后遍历第二个数 \(W\)

由于 \(n = L × W × H\),当知道前两个数时,第 \(3\) 个数也随之确定

当 \(W\ne H\) 时,\(W\) 的值与 \(H\) 的值交换算是两种方案

因此,只需确定 \(W< \sqrt{\dfrac{n}{L}}\) 的 \(W\) 取值数量,然后乘以 \(2\)

再单独确定 \(W=\sqrt{\dfrac{n}{L}}\) 时是否满足条件,此时只算做一种方案

程序运行时间很长,最后没跑出来

public class Main {
    public static void main(String[] args) {
        final long n = 2021041820210418l;
        long ans = 0;
        for (long l = 1; l <= n; ++l) {
            if (n % l != 0) continue;
            final long rest = n / l;
            long w;
            for (w = 1; w * w < rest; ++w) {
                if (rest % w == 0) ans += 2;
            }
            if (w * w == rest) ++ans;
        }
        System.out.println(ans);
    }
}

思路二

比赛时最开始想到的思路

先处理出 \(n\) 的所有因子,再三重循环(或 \(DFS\))选出三个因子,相乘是否等于 \(n\)

public class Main {
    public static void main(String[] args) {
        long[] num = new long[1000];
        int cnt = 0;
        final long n = 2021041820210418l;
        long now = 1;
        while (now * now < n) {
            if (n % now == 0) {
                num[cnt++] = now;
                num[cnt++] = n / now;
            }
            ++now;
        }
        long ans = 0;
        for (int i = 0; i < cnt; ++i) {
            for (int j = 0; j < cnt; ++j) {
                for (int k = 0; k < cnt; ++k) {
                    if (num[i] * num[j] * num[k] == n) {
                        ++ans;
                    }
                }
            }
        }
        System.out.println(ans);//2430
    }
}

思路三

若 \(L\leq W\leq H\),则:

  1. 当 \(L=W=H\) 时,生成方案数为 \(1\)
  2. 当 \(L=W < H\) 或 \(L< W=H\) 时,生成方案数为 \(3\)
  3. 当 \(L<W<H\) 时,生成方案数为 \(6\)
public class Main {
    public static void main(String[] args) {
        final long n = 2021041820210418l;
        long ans = 0;
        for (long i = 1; i * i * i <= n; ++i) {
            if (n % i != 0) continue;
            long rest = n / i;
            for (long j = i; j * j <= rest; ++j) {
                if (rest % j != 0) continue;
                long k = rest / j;
                if (i < j && j < k) ans += 6;
                else if (i == j && j == k) ans += 1;
                else ans += 3;
            }
        }
        System.out.println(ans);//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\) 之间的最短路径长度是多少。

提示:建议使用计算机编程解决问题。

答案为:\(10266837\)

思路

很明显最短路算法

数据范围很小采用邻接矩阵存图

\(Floyd\) 求全源最短路

import java.util.Arrays;

public class Main {
    static int gcd(int x, int y) {
        return y == 0 ? x : gcd(y, x % y);
    }

    static int lcm(int x, int y) {
        return x / gcd(x, y) * y;
    }

    static final int N = 2021;
    static final int INF = (int) 1e9;
    //dis[i][j]表示i->j的路径长度
    static int[][] dis = new int[N + 1][N + 1];

    //运行Floyd之后,dis[i][j]变为 i->j的最短路径长度
    static void Floyd() {
        for (int k = 1; k <= N; ++k)
            for (int i = 1; i <= N; ++i)
                for (int j = 1; j <= N; ++j)
                    dis[i][j] = Math.min(dis[i][j], dis[i][k] + dis[k][j]);
    }

    public static void main(String[] args) {
        for (int i = 0; i <= N; ++i) Arrays.fill(dis[i], INF);
        for (int i = 1; i <= N; ++i) {
            for (int j = i + 1; j <= N; ++j) {
                if (j - i <= 21) {
                    dis[i][j] = dis[j][i] = lcm(i, j);
                }
            }
        }
        Floyd();
        System.out.println(dis[1][2021]);//10266837
    }
}

\(Dijkstra\) 求单源最短路

待补充

试题 F 时间显示

问题描述

小蓝要和朋友合作开发一个时间显示的网站。在服务器上,朋友已经获取了当前的时间,用一个整数表示,值为从 \(1970\) 年 \(1\) 月 \(1\) 日 \(00:00:00\) 到当前时刻经过的毫秒数。

现在,小蓝要在客户端显示出这个时间。小蓝不用显示出年月日,只需要显示出时分秒即可,毫秒也不用显示,直接舍去即可。

给定一个用整数表示的时间,请将这个时间对应的时分秒输出。

【输入格式】

输入一行包含一个整数,表示时间。

【输出格式】

输出时分秒表示的当前时间,格式形如 \(HH:MM:SS\),其中 \(HH\) 表示时,值为 \(0\) 到 \(23\),\(MM\) 表示分,值为 \(0\) 到 \(59\),\(SS\) 表示秒,值为 \(0\) 到 \(59\)。

时、分、秒不足两位时补前导 0。

【样例输入 1】
46800999
【样例输出 1】
13:00:00
    
【样例输入 2】
1618708103123
【样例输出 2】
01:08:23

【评测用例规模与约定】

对于所有评测用例,给定的时间为不超过 \(10^{18}\) 的正整数

Code

import java.util.Scanner;

public class F {
    //计算一天有多少毫秒
    static final long dayMS = 24 * 60 * 60 * 1000;

    public static void main(String[] args) {
        long n = new Scanner(System.in).nextLong() % dayMS;
        long h = n / (60 * 60 * 1000);
        long m = n / (60 * 1000) % 60;
        long s = n / 1000 % 60;
        System.out.println(String.format("%02d:%02d:%02d", h, m, s));
    }
}

试题 G 最少砝码

问题描述

你有一架天平。现在你要设计一套砝码,使得利用这些砝码可以称出任意小于等于 \(N\) 的正整数重量。

那么这套砝码最少需要包含多少个砝码?

注意砝码可以放在天平两边。

思路

原文链接:

  1. 第十二届蓝桥杯省赛JavaB组 试题 G: 最少砝码_小小风0的博客-CSDN博客
  2. 第十二届蓝桥杯省赛 Java B组 试题 G: 最少砝码_山雾野灯的博客-CSDN博客
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        int n = new Scanner(System.in).nextInt();
        int weight = 1, count = 1, ans = 1;
        while (count < n) {
            weight *= 3;
            count += weight;
            ++ans;
        }
        System.out.println(ans);
    }
}

参考资料

第十二届蓝桥杯省赛JavaB组 试题 G: 最少砝码_小小风0的博客-CSDN博客

第十二届蓝桥杯省赛 Java B组 试题 G: 最少砝码_山雾野灯的博客-CSDN博客

标签:12,int,long,蓝桥,++,static,now,public,组省赛
From: https://www.cnblogs.com/Cattle-Horse/p/17044968.html

相关文章

  • 【题解】CF1268C K Integers
    萌新不懂就问,这是什么时代的题啊???思路trick题。首先根据trick可知:先将\([1,k]\)中的数聚在一起再排序是最优的。排序的花费是逆序对数,所以现在的问题是求把\([1,......
  • Codeforces 1278 F Cards 增强版 题解 (斯特林数,推式子)
    原题链接增强版链接增强版中k=1e7为啥网上题解的式子都那么长啊.jpg首先令\(p=\frac1m\)。求某个数的次幂的题通常都是无脑转下降幂:\(x^k=\sum_{i=0}^kS_2(k,i)x^{\u......
  • 121. Best Time to Buy and Sell Stock [Easy]
    121.BestTimetoBuyandSellStockYouaregivenanarraypriceswhereprices[i]isthepriceofagivenstockontheithday.Youwanttomaximizeyourprof......
  • daily study 12
    学习c语言的操作符的知识与使用分类:1.算数操作符+,-,*,/,%2.移位操作符<<,移动二进制位。溢出的丢弃,缺少的补上>>(1)算术右移右边丢弃,左边补原位(2)逻辑右移右边丢弃左边补03.位操作......
  • windows2012通过powershell安装远程组件技巧
    概要:通过服务器管理器安装远程桌面服务会报错一直没有办法解决之后了解到安装组件可以通过power命令安装 powershell命令说明https://docs.microsoft.com/en-us/wind......
  • 为什么页面不能识别"\n\r"而控制台的f12可以?
    今天看项目代码的时候突然发现这么一个现象,代码如下左边是页面上的样式,右边是f12里面的element.它们展现的方式不一样.研究了好一会儿,最终也只有一个猜想,并没有得到......
  • 混乱与整齐-布局-PCB系列教程1-12
     搞电子的人,通常看上去总是混乱的。当然,更乱的是桌面。下图是模电领域大神JimWilliams大师(1948-2011)与他的办公桌。但是电子工程师的作品,却要求整齐。电路板是工业时代的......
  • 电子设计教程12:Buck降压电路
      我们仍然使用MC34063芯片,来设计一个DC-DC降压电路,实现直流12V转5V。Buck变换器  Buck变换器是开关电源基本拓扑结构的一种,Buck变换器又称为降压变换器,是一种对输入电......
  • STM32自带GB2312字库显示汉字
      本文介绍如何把字库文件写入单片机的flash中,然后无需再提取字模,即可实现单片机显示中文字符的功能。下载字库到单片机flash中的指定位置  在​​上一篇博客​​中,最后......
  • P3225 [HNOI2012]矿场搭建 tarjan
    //题意:在一幅无向图图上,删除一个点后,其他所有点上的人还能通过其他点出去,问最少设置几个出口,以及方案数//思路:无向图就联想到双联通分量,我们来分类讨论一下//1......