十二届蓝桥杯Java大学B组

本文包含一系列编程问题的解决方案,涉及ASCII码转换,通过取余和除法拆解数字,直线的参数表示,计算直线数量,全排列求解货物摆放方法,以及时间显示的计算方法。主要运用了算法和数学概念如最小公倍数和最大公因数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

试题A: ASC

ASCII:A——65
ASCII:L——76

试题B:卡片

其实我们随便推导一下就知道,第一个元素不够的肯定是1,(0,2,3等)元素肯定是有多的,因为1消耗的优先级最高。

本题思路就是通过 取余除10 两个步骤对一个数字进行逐步拆解

例子:131  ①先取余131%10 = 1;   one--;   131/10 = 13;

                   ②13%10 = 3;one不变;    13/10 = 1;

                   ③1%10 = 1 ;    one--  ;        1/10 = 0;跳出while循环,操作下一个数字

public static void main(String[] args) {

        //one表示1还剩余多少卡片
        int one = 2021;
        //temp用来保存当前数字i的值
        int temp = 0;
        int ans = 0;
        
        for (int i = 1;one>0; i++) {
            temp = i;
            while(temp != 0){
                //通过取余运算来获得temp最后一个数字是不是1,是1就对卡片one--
                if(temp%10 == 1){
                    one--;
                }
                //取余后相当于3位数(121)->(12),直到3位数字全部消耗完
                temp = temp/10;
            }
            //ans用来保存当前的数字
            ans = i;
        System.out.println(hhh);
    }

试题C:直线

我们只需要保存 两个点之间函数:y=kx+b中,k和b即可,如果k,b相同,则这个线不计入结果

public class Main{
    static List<String> list = new ArrayList<>();
    //最小公约数
    static int gcd(int a,int b) {
        if(b==0) return a;
        return gcd(b,a%b);
    }
    public static void main(String[] args) {
        for(int x1 = 0; x1 < 20; x1++) {
            for(int y1 = 0; y1 < 21; y1++) {
                for(int x2 = 0; x2 < 20; x2++) {
                    for(int y2 = 0; y2 < 21; y2++) {
                        if(x1 != x2) {
                            //可以理解我们保存的是 String版本的 k 和 b
                            String str = "";//存储k和b
                            int y = y2 - y1;
                            int x = x2 - x1;
                            int g = gcd(y,x);//求两个数的最小公因数,记录最简分数
                            //k = (y2 - y1) / (x2 - x1); 如果y=8,x=4 => y/g=2  x/g = 1 => k=2/1
                            str =  y / g + "/" + x / g;
                            //b =( y * (x2 - x1) - x * (y2 - y1)) / (x2 - x1)
                            int b = y1 * x - x1 * y;
                            int g1 = gcd(b, x);
                            str = str +"&"+ b / g1 + "/" + x / g1;
                            list.add(str);
                        }
                    }
                }
            }
        }
        long ans = 0;
        Map<String, Integer> map = new HashMap<>();
        for(int i = 0; i < list.size(); i++) {
            //遍历每个List保存的函数,如果kb相同,那么这个线就已经存在了
            if(!map.containsKey(list.get(i))) {
                ans++;
                map.put(list.get(i), 1);
            }
        }
        //这里是因为4层for循环里面,没有计算所有k=0(x1 = x2)的情况,故加上20个竖线
        System.out.println(ans+20);
    }
}

试题D:货物摆放

此题是全排列

非常简单,我们用hashset保存2021041820210418的所有因子

因子:2*2=4,1*4=4;    1,2,4就是4的因子

3层for循环从因子数组中,找出所有arr[i]*arr[j]*arr[k] == 2021041820210418的情况,每一个情况都是一种货物摆放的方法

import java.util.*;
public class Main{
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        int ans = 0;
        //用一个HashSet保存所有的因子————因子:2*2=4,1*4=4; 1,2,4就是4的因子
        Set<Long> all = new HashSet<>();
        long num= 2021041820210418L;
        //此处用over保存了num的开平方的值,刚好他也能开平方,开平方后得到的答案不会改变的
        Long over = (long)Math.sqrt(num);
        //找到目标数字因子
        for (long i = 1; i <= over; i++) {
            //如果i是因子,就表示num可以整除i没有余数
            if(num%i == 0){
                //此时HashSet就可以加入i和num/i
                all.add(i);
                all.add(num/i);
            }
        }

        //把HashSet转化成数组,数组保存的是Long类型
        Long[] arrs = all.toArray(new Long[0]);

        for (int i = 0; i < arrs.length; i++) {
            for (int j = 0; j < arrs.length; j++) {
                for (int k = 0; k < arrs.length; k++) {
                    //判断3个因子相乘等于num就表示一种堆叠的类型
                    if(arrs[i]*arrs[j]*arrs[k] == num){
                        ans++;
                    }
                }
            }
        }
        System.out.println(ans);
        scan.close();
    }
}

试题F:路径

此题利用了①俩点间最小公倍数求法②Floyd算法求联通路径(可以换成迪杰斯特拉更好)

思路:找到俩点间最小距离利用Floyd算法判断;

        如果俩点间绝对值相减大于21,那么通过我们定义的一个Max表示距离无限大来表示;

import java.util.*;
public class Main{
    //1.如果前面的数是他的因子,那么权值就会很小
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        //Max用于表示两个点直接无连接
        long Max = 999999999;
        //arr保存了所有点之间的路径大小
        long[][] arr = new long[2021][2021];
        for (int i = 0; i < 2021; i++) {
            for (int j = 0; j < 2021 ; j++) {
                //如果两个点超过了21,那么就设置俩点无限长
                if(Math.abs(i-j)>21){
                    arr[i][j] = Max;
                }else if(i != j){
                    arr[i][j] = gbs(i+1,j+1);   //俩点不相等,保存俩点的距离——最小公倍数
                }else {
                    arr[i][j] = 1;
                }
            }
        }
        //Floyd算法,判断:俩点间多了一个第三者,通过第三者能不能让俩点距离更近,如果可以就通过第三者联系二点
        for (int i = 0; i < 2021; i++) {
            for (int j = 0; j < 2021; j++) {
                for (int k = 0; k < 2021; k++) {
                    if(arr[i][j]>arr[i][k]+arr[k][j]){
                        arr[i][j] = arr[i][k]+arr[k][j];
                    }
                }
            }
        }
        System.out.println(arr[0][2020]);
        scan.close();
    }
    //利用最大公因数,求最小公倍数
    public static long gbs(long a,long b){
        long gb = pcb(a,b);
        gb = (a/gb) * (b/gb) *gb;
        return gb;
    }
    //求最大公因数
    public static long pcb(long a,long b){
        if(b == 0) return a;
        return pcb(b,a%b);
    }
}

试题F:时间显示

非常简单,关键在于怎么准确表达出①1天内剩余的时间  ②剩余的秒数  ③剩余的分钟数  ④剩余的小时数

import java.util.*;
public class Main{
    //1.如果前面的数是他的因子,那么权值就会很小
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        long total = scan.nextLong();
        int day = 24*60*60; //一天day秒
        //all为一天以内的时间
        int all = (int)(total/1000)%day;
        //秒:SS ->   all%60  可以得到秒的余数
        long SS = all%60;
        //分:MM ->   all/60=总分钟数  all/60%60分钟数余数
        long MM = all/60%60;
        //时:HH ->   all/3600=总小时数   all/3600%24小时数余数
        long HH = all/3600%24;
        String S = ""+SS;
        String M = ""+MM;
        String H = ""+HH;
        //SS,MM,HH如果小于10,直接输出就会只有一个数,应该在前面加个0凑足两位数
        if(SS < 10)     S = "0"+SS;
        if(MM < 10)     M = "0"+MM;
        if(HH<10)       H = "0"+HH;
        System.out.println(H+":"+M+":"+S);
        scan.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值