0
点赞
收藏
分享

微信扫一扫

第十二届蓝桥杯JavaB组省赛(题目及AC题解)

忆北文学摄影爱好员 2022-03-11 阅读 45
java算法

文章目录

题一:ASCII码

题二:卡片–暴力循环

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        //0-9出现的次数
        int index[] = new int[9];

        flag:for (int i = 1; ; i++) {
            int[] ints = new int[String.valueOf(i).length()];
            //把int 转为int 数组
            for (int j = 0; j < String.valueOf(i).length(); j++) {
                //获得该数组的每一个数字
                ints[j] = Integer.parseInt(String.valueOf(String.valueOf(i).charAt(j)));
                //遍历添加数字
                for (int k = 0; k < 9; k++) {
                    if(ints[j]==k){
                        index[k]++;
                        //注意结束的条件,当等于2021时,说明卡片全部用完,这个时候输出i
                        if (index[k]==2021){
                            System.out.println(i);
                            System.out.println("此时用牌的数量"+Arrays.toString(index));
                            break flag;
                        }
                    continue;
                    }
                }
            }
        }
    }
}

题三:直线–Set集合/浮点数运算

import java.util.HashSet;
public class Main {
    public static void main(String[] args) {
        HashSet<String> set=new HashSet<>();//用了set的互异性集合中不能有相同的元素
        double k,b;
        for(int x1=0;x1<20;x1++){
            for(int y1=0;y1<21;y1++){
                for(int x2=x1+1;x2<20;x2++){
                    for(int y2=0;y2<21;y2++){
                        k=(y2-y1)*1.0/(x2-x1);
                        b=(y1*x2-x1*y2)*1.0/(x2-x1);//注意要乘以1.0有小数斜率
                        set.add(k+","+b);//用字符串来表示每个点
                    }
                }
            }
        }
        for (String s :
                set) {
            System.out.println(s);
        }
        System.out.println(set.size()+20);//最后记得加上斜率不存在的
    }
}

题四:货物摆放–大数的因数

import java.util.*;
public class Main{
    public static void main(String[] args) {
        long n = 2021041820210418l;
        int count = 0;
        List<Long> list = new ArrayList<>();
        for (long i = 1; i * i <= n; i++) {
            //求所有公因子的方法 很大程度上提高了效率
            if (n % i == 0) {
                list.add(i);
                if (i != n / i) {
                    list.add(n / i);
                }
            }
        }
        for (long i : list) {
            for (long j : list) {
                for (long k : list) {
                    if (i * j * k == n) {
                        count++;
                        break;
                    }
                }
            }
        }
        System.out.println(count);
    }
}

题五:路径–dijkstra算法

public class Main {
    //答案:10266837
    final static int C = 999999999;//定义该点无直达
    public static void main(String[] args) {
        //初始化邻接矩阵
        int[][] map = new int[2050][2050];
        //首先初始化为最大值
        for (int[] temp : map) {
            for (int i = 0; i < temp.length; i++) {
                temp[i] = C;
            }
        }
        //按照题意赋值
        for (int i = 1; i <= 2021; i++) {
            for (int j = i; j <= i + 21; j++) {
                //对a,b相差21以内的边赋权
                map[i][j] = lcm(i, j);
            }
        }
        //Dijkstra:按路径长度递增次序产生最短路径
        /*
        V:代表所有顶点
        bj:代表顶点是否已确定最短路径
        */
        boolean bj[] = new boolean[2050];//用来标记该点是否找到最短路径
        int dis[] = new int[2050];//存储源点到其他顶点的初始路径
        for (int i = 1; i <= 2021; i++)
            dis[i] = map[1][i];//先赋值为直达路径
        int min, minIdx = 0;
        //没执行一次while循环,确定到一个点的最短路径
        while (!bj[2021]) {//如果2021点的最短路径还没求到就一直循环
            min = Integer.MAX_VALUE;
            //每次找到从源点出发最近的距离
            for (int i = 2; i <= 2021; i++) {
                if (!bj[i] && dis[i] < min) {
                    //交换
                    min = dis[i];
                    minIdx = i;
                }
            }
            bj[minIdx] = true;//循环一圈以后,可以确定一个最短的点,然后进行下一次循环,直到bj[2021]==true

            //从最近的这个点当中间点,找到 V(0) -- V(minIdx) -- V(和V(minIdx)有直连的点),再一次更新最短路径
            for (int i = minIdx + 1; i <= minIdx + 21; i++) {
                //如果该点到源点没有边
                if (dis[i] == C)
                    dis[i] = dis[minIdx] + map[minIdx][i];
                //两边之和小于直达边,更新距离
                else if (dis[minIdx] + map[minIdx][i] < dis[i])
                    dis[i] = dis[minIdx] + map[minIdx][i];          
            }
        }
        System.out.println(dis[2021]);
    }
    //求最大公约数
    public static int gcd(int x, int y) {
        if (y == 0)
            return x;
        return gcd(y, x % y);
    }
    public static int lcm(int x, int y) {//最小公倍数
        return x * y / gcd(x, y);
    }
}

题六:时间显示–Calendar类

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Calendar date = Calendar.getInstance();
        //初始化date对象
        date.set(1970,1,1,0,0,0);
        Scanner scanner = new Scanner(System.in);
        BigDecimal num = scanner.nextBigDecimal();
        BigDecimal temp = new BigDecimal("20000000");
        BigDecimal[] arr = num.divideAndRemainder(temp);
        for (int i = 0; i < arr[0].intValue(); i++) {
            date.add(Calendar.MILLISECOND,20000000);
        }
        date.add(Calendar.MILLISECOND,arr[1].intValue()/1000*1000);

        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        System.out.println(date.getTime());
        String ans = format.format(date.getTime());
        System.out.println(ans);
    }
}

题七:最少砝码

import java.util.*;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		long n = sc.nextLong();
		long ans = 0;
		while(n>0) {
			n -= Math.pow(3, ans);
			ans++;
		}
		System.out.println(ans);
	}
}

题八:杨辉三角形-搞不懂

正确代码

import java.util.Scanner;
public class Main{
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()) {
			System.out.println(solve(sc.nextLong()));
		}
	}
	public static long solve(long n) {
		long res = 0l;
		long san[] = new long[50010];
		san[1]=1;
            //san[x]表示当前层的第x个位置,这是为了方便后面在每层第一个位置执行san[j] = san[j-1]+san[j]不出现数组越界的情况
		if(n==1)return 1;
		long cur=0l;
		for(int i=2;i<50000;i++) {
			//cur现在所在的位置是上上层的最后一个位置
			//然后通过+i是到了本层第一个位置,再加i-1就到了这层最后一个位置
			//加一起也就是cur+2*i-2
			cur+=2*i-1;
			for(int j=i;j>=1;j--) {
				san[j] = san[j-1]+san[j];
				if(san[j]==n)res=cur;
				cur--;
			}
			//这里一直减到了本层第一后位置后还要--,所以一层循环完cur的位置就到了上一层的最后一个位置
			//下一次循环的时候i++了,所以下一次循环开始前cur的位置是上上层的最后一个位置
			if(res!=0)return res;
		}
		//在前五万行都找不到n这个数,也就是说n这个数不可能出现在五万行以后的第二个位置
		//因为五万行以后的第二个位置的值都比1000000000大,所以n第一次出现的位置必然是第n+1行的第三个位置,也就是C上标1,下标n的值
		
		return (n+1)*n/2+2; 
		//第一行是1个数,第n行是n个数,而且是等差数列,用等差数列求和公式算出前n行的值加2就是n+1行第二个数的位置了
	}
}

题九:双向排序–暴力Api

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int length = sc.nextInt();//数组长度
        int op = sc.nextInt();//操作次数
        //初始化数组
        Integer[] arr = new Integer[length];
        for (int i = 0; i < length; i++) arr[i] = i + 1;
        
        for (int i = 0; i < op; i++) {
            //接受两个数字并处理
            int num = sc.nextInt();
            int num2 = sc.nextInt();
            if (num == 0) {// ai-an降序排列
                //降序排列
                //从fromIndex到toIndex-1的元素排序!!!
                Arrays.sort(arr, 0, num2, new Comparator<Integer>() {
                    public int compare(Integer a, Integer b) {
                        return b - a;
                    }
                });
                continue;
            }
            if (num == 1) {
                Arrays.sort(arr, num2-1, length);
                continue;
            }
        }
        for (int i : arr) System.out.print(i + " ");
    }
}

题十:括号序列

CSDN AC题解

举报

相关推荐

0 条评论