2022java蓝桥杯算法训练
1.印章:
代码:

1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner s=new Scanner(System.in); 6 int n=s.nextInt(); 7 int m=s.nextInt(); 8 double p=1.0/n; 9 10 double[][] b=new double[m+1][n+1]; 11 if (n==1){ //当n=1时m>n几率为1 12 b[m][n]=1; 13 System.out.printf("%.4f",b[m][n]); 14 return; 15 } 16 if (n>1&&m<n){ //当m<n时几率为0 17 b[m][n]=0; 18 System.out.printf("%.4f",b[m][n]); 19 return; 20 } 21 for (int i = 1; i <=m; i++) { 22 for (int j = 1; j <=n; j++) { 23 if (i<j) b[i][j]=0; //当m<n时几率为0 24 if (j==1){ 25 b[i][j]=Math.pow(p,i-1); //当i张集齐1种的概率 26 }else { 27 b[i][j]=b[i-1][j]*(j*1.0/n)+b[i-1][j-1]*((n-j+1)*1.0/n); //当i张集齐j种的概率 28 } 29 30 } 31 32 } 33 34 System.out.printf("%.4f",b[m][n]); 35 36 } 37 }
2.拿金币:
代码:

1 import java.util.Scanner; 2 3 4 public class Main { 5 6 /* 7 * 输入:第一行,整数n,表示N*N的一个矩阵。 8 * n行,初始化,每个矩阵的大小。每个数不能找过1000. short类型。 9 * 格式要求:n小于1000 short类型 10 * */ 11 12 /* 13 * 输出:一行整数sum,表示的是矩阵从左上角到右下角的最大和。 int类型 14 * w*/ 15 16 //程序思路: 17 //1.接受n,创建一个数组 18 //2.初始化数组。 19 //3.求和。 20 21 public static void main(String[] args){ 22 //1.接受n,创建一个数组 23 Scanner input = new Scanner(System.in); 24 short n = input.nextShort(); 25 26 //2.初始化数组。 27 int[][] arrys = new int[n][n]; 28 for (int i = 0; i <n ; i++) { 29 for (int j = 0; j <n ; j++) { 30 arrys[i][j] = input.nextInt(); 31 32 } 33 34 } 35 36 37 38 39 40 41 42 43 //3.求和 44 for (int i = 0; i < n; i++) { 45 for (int j = 0; j < n; j++) { 46 //初始化固定部分,arrys[0][0]-a[0][n-1]。a[0][0]-a[n-1][0]。 47 //因为从这一部分走,方向是唯一,也就是和是唯一的,没有别的路。 48 if (i==0&&j==0)//初始化首位。 49 continue; 50 51 52 if (i == 0) {//首行非首位。 53 arrys[i][j] = (arrys[i][j-1]+arrys[i][j]);//运算+ - 至少要int类型,所以会被强制转换,而不是下标问题。 54 continue; 55 56 } 57 58 if (j == 0) {//首列,非首位。 59 arrys[i][j] = (arrys[i-1][j]+arrys[i][j]); 60 continue; 61 } 62 63 if (arrys[i - 1][j] > arrys[i][j - 1]) {//上比左大。 64 arrys[i][j] = (arrys[i][j]+arrys[i-1][j]); 65 }else arrys[i][j] =(arrys[i][j]+arrys[i][j-1]);//左比上大。 66 67 68 } 69 } 70 71 72 System.out.println(arrys[n-1][n-1]); 73 74 } 75 76 }
3.数字游戏:
代码:

1 import java.util.Scanner; 2 /* 3 * 4 * */ 5 public class Main { 6 7 static int n;//初始的n个数 8 static int sum;//相加的结果 9 static int arr1[]; 10 static boolean bool = true;//标记是否找到n个元素 11 12 public static void main(String[] args) { 13 Scanner sc = new Scanner(System.in); 14 n = sc.nextInt(); 15 sum = sc.nextInt(); 16 17 int array[] = new int[n]; 18 int visit[] = new int[n+1]; //访问标记 19 20 dfs(0, array, visit); 21 } 22 23 //step:当前已经遍历的元素数;array:存放当前遍历的元素; visit:标记当前哪些元素已被访问; 24 public static void dfs(int step,int arr[], int vis[]){ 25 if(step == n){//1.找到n个数字,检查这n个数相加是否等于sum 26 int arr1[] = new int[n]; 27 for(int i=0;i<n;i++){//先将array数组中的元素 放到arr1 28 arr1[i] = arr[i]; 29 }//for 30 31 for(int i=1;i<n;i++){//累加到arr1[0] 32 for(int j=0;j<n-i;j++){ 33 arr1[j]=arr1[j]+arr1[j+1]; 34 } 35 }//for 36 37 if(arr1[0] == sum){//累加后与sum相等,则输出 38 for(int i:arr){ 39 System.out.print(i+" "); 40 } 41 bool = false;//已经找到符合要求的n个元素 42 return; 43 }else{//累加后与sum不相等,退出重新查找 44 return; 45 } 46 47 }//if 48 if(bool == true){//2.没有找到符合要求的n个元素 49 for(int i=1;i<=n;i++){ 50 if(vis[i]==0){//i值没有使用过 51 arr[step]=i;//存储当前访问的元素 52 vis[i]=1; 53 dfs(step+1,arr,vis);//从当前这个元素起,重新进行遍历 54 vis[i]=0; 55 } 56 } 57 }//if 58 return; 59 } 60 }
4.无聊的逗:
代码:

1 import java.util.Scanner; 2 public class Main { 3 public static void main(String[] args) { 4 Scanner cin=new Scanner(System.in); 5 int ans=Integer.MIN_VALUE; 6 int n = cin.nextInt(); 7 int []array=new int[1<<n]; 8 int []nums=new int[n]; 9 for(int i=0;i<n;++i){ 10 nums[i]=cin.nextInt(); 11 array[1<<i]=nums[i]; 12 } 13 for(int i=0;i<1<<n;++i){ 14 for(int j=0;j<n;++j){ 15 if((i&(1<<j))==0)continue; 16 array[i]=array[i-(1<<j)]+nums[j]; 17 break; 18 } 19 } 20 for(int i=1;i<(1<<n);++i){ 21 int j=(1<<n)-i-1; 22 for(int k=j;k>0;k=(k-1)&j){ 23 if(array[k]==array[i]) 24 ans=Math.max(array[k],ans); 25 } 26 } 27 System.out.print(ans); 28 } 29 }
5.礼物:
思路:
a.只能拿一次,2k,从开头拿起。所以分为前k0,后k1,并且两者要相等。k0 和k1 都要小于s。最后再输出.k的值。
b.在循环赋值当中,保存每一项累加的结果到数组当中
c.通过二分查找的方式找到前面的k0的大小,再匹配后面k1的总和是否也满足,满足就直接输出,不满足就降低k0的值来重新寻找。
代码:

1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 public class Main{ 5 static int count =0; 6 static long S; 7 public static void main(String args[]) { 8 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 9 String s,s2; 10 String[] b1 = null,b2 = null; 11 try { 12 s=br.readLine(); 13 b1=s.split(" "); 14 s2=br.readLine(); 15 b2=s2.split(" "); 16 17 } catch (IOException e) { 18 // TODO Auto-generated catch block 19 e.printStackTrace(); 20 } 21 int N=Integer.parseInt(b1[0]); 22 S=Long.parseLong(b1[1]); 23 24 int[] a=new int[N+1]; 25 long[] sum=new long[N+1]; 26 for(int i=1;i<=b2.length;i++) { 27 a[i]=Integer.parseInt(b2[i-1]); 28 sum[i]=sum[i-1]+a[i]; 29 } 30 int l=1,r=N; 31 while(l<r) { 32 int mid=(l+r+1)/2; 33 if(fun(mid,N,sum)) { 34 l=mid; 35 }else { 36 r=mid-1; 37 } 38 } 39 System.out.print(2*l); 40 } 41 public static boolean fun(int mid,int n,long[] sum) { 42 for(int i=mid;i<=n-mid;i++) { 43 if(sum[i]-sum[i-mid]<=S&&sum[i+mid]-sum[i]<=S) { 44 return true; 45 } 46 } 47 return false; 48 } 49 }
总结:
a.Scanner 类不适合输入太多的值的情况,容易引起内存过大,这时可以考虑BufferedReader类来完成输入流的操作。归属java.io.BufferedReader.和java.io.InputStreamReader
用法是 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)
String s =br.readLine()//读取一整行。
String[] ss = s.split(" ")//根据空格来分割字符串为数组。
b.考虑大小,数组可以是int 类型,但是求和的时候可能会超过,所以最好用long数组。
c.paresInt 和parselong 参数一样,都是用的是字符串,最后转换为整形类型,虽然输出的的时候还是字符串,所以可以根据是否要用于做运算来抉择,加减乘除的运算至少是int类型才能,所以byte ,short适合不做运算的情况来使用,避免频繁装箱。
6.跳马:
代码如下:

1 import java.util.*; 2 3 import static java.lang.System.in; 4 import static java.lang.System.out; 5 6 public class Main { 7 static Deque<int[]> list = new LinkedList<int[]>(); // 这个集合记录每一次走的过程,因为只涉及插入和删除,我用Deque。 8 static int[][] steps = new int[][]{{1, 2}, {1, -2}, {-1, 2}, {-1, -2}, {2, 1}, {2, -1,}, {-2, 1}, 9 {-2, -1}}; // 因为马只能走“日”,所以这个二维数组给出所有马能够走的方向,共八方。 10 11 public static void main(String[] args) { 12 13 Scanner sc = new Scanner(System.in); 14 int a = sc.nextInt(), b = sc.nextInt(), c = sc.nextInt(), d = sc.nextInt(), len = steps.length; 15 out.println(getCount(a, b, c, d, len)); 16 } 17 18 /** 19 * @param a 对应题目中的a 20 * @param b 对应题目中的b 21 * @param c 对应题目中的c 22 * @param d 对应题目中的d 23 * @param len steps数组的长度 24 * @return 返回最短的次数 25 */ 26 public static int getCount(int a, int b, int c, int d, int len) { 27 list.offer(new int[]{a, b}); // 先将起始位置加进来 28 int count = 0, innerCount = 0; //count为最后的返回值,innerCount后面会讲 29 if (list.getFirst()[0] == c && list.getFirst()[1] == d) { // 如果起始位置等于最终的位置,我们直接返回count。 30 return count; 31 } 32 33 boolean flag = true; // 死循环退出标识 34 while (flag) { 35 for (int i = 0; i < len; i++) { // 最外层的for循环是控制马走的方向 36 int[] at = new int[2]; // 临时的at数组装载每一次当前位置的下一个位置 37 for (int j = 0; j < 2; j++) { // 该循环每次都更新马当前位置可走的方向,比方说马当前在(1,1),完成一次该for循环,马就出现了下一个可以走的位置,存到list里面, 38 // 如果两层for循环都完成马就会出现8个当前位置可以走的下一个位置,存入list中 39 at[j] = list.getFirst()[j] + steps[i][j]; 40 } 41 list.offer(at); // 存入下一个位置到list 42 innerCount++; // 每一个存入innerCount就会+1,当这里的加1并不能表示次数。因为如果马用的步数为1的时候,innerCount的会是8,而步数用的是2时,innerCount为64 43 if (at[0] == c && at[1] == d) { // 符号条件,则把退出表示设置为false 44 flag = false; 45 break; 46 } 47 } 48 if (Math.pow(8, count + 1) == innerCount) // 基于42行的说法,所以有了当前的判别式。 49 count++; 50 list.pollFirst(); // 当当前位置下一步可走的8个方向存入list中,我们删除当前方向,判别下一个方向 51 } 52 return count + 1; 53 } 54 55 }
7.kAc给糖果你吃:
代码如下:

1 import java.util.Scanner; 2 public class Main { 3 4 /* 5 * 输入:两行,第一行n(表示有多少堆),m(表示拿的次数) 6 * 第二行:n个数字(初始化每堆糖果的个数) 7 * 格式要求:n在0--1000,其他的是10亿。(int类型) 8 * */ 9 10 /* 11 * 输出:一行,整数,s,表示最多拿多少糖果。 12 * */ 13 14 15 16 17 //程序: 18 19 20 21 22 public static void main(String[] args){ 23 24 //1.接收n,m,初始化数组。 25 Scanner input = new Scanner(System.in); 26 int n = input.nextInt(); //n 27 // System.out.println("n:"+n); 28 int m = input.nextInt(); //m 29 // System.out.println("m:"+m); 30 int[] array = new int[n];//A【i】 31 long sum = 0;//sum 32 for(int i =0 ; i<n ; i++){ 33 array[i] = input.nextInt(); 34 // System.out.println(array[i]); 35 }//for 36 37 //2.查找m次最大值,使用选择排序 38 for(int i=0; i<m;i++){ 39 for(int j = i+1;j<n;j++){ 40 if(array[i]<array[j]){ 41 //交换 42 int temp = array[j]; 43 array[j] = array[i]; 44 array[i] = temp; 45 }//if 46 47 //把每次最大值相加; 48 49 }//for 50 sum = sum + array[i]; 51 }//for 52 53 System.out.println(sum); 54 }//main 55 }//类
8.数的潜能:
代码如下:

1 import java.util.Scanner; 2 public class Main{ 3 public static void main(String args[]) { 4 Scanner sc=new Scanner(System.in); 5 long n=sc.nextLong(); 6 //a 3的数量,b 2的数量 7 long a=0; 8 int b=0; 9 int[] x=new int[100]; 10 long[] z=new long[100]; 11 //a 3的数量,b 2的数量 12 if(n%3==1) { 13 a=(n/3)-1; 14 b=2; 15 }else if(n%3==2) { 16 a=n/3; 17 b=1; 18 }else { 19 a=n/3; 20 } 21 //c a个3相乘取模的当前位置 x[]与z[]记录相应的取模值及取模位置,d 后一半剩余相乘数量。 22 long c=1; 23 int yu=3%5218; 24 int k=0; 25 x[0]=yu; 26 z[0]=c; 27 while(a>=2*c) { 28 yu=(yu*yu)%5218; 29 x[++k]=yu; 30 c*=2; 31 z[k]=c; 32 } 33 long d=a-c; 34 for(int i=k-1;i>=0;i--) { 35 if(d>z[i]) { 36 yu=(yu*x[i])%5218; 37 d=d-z[i]; 38 } 39 } 40 yu=(int) ((yu*Math.pow(3, d)*Math.pow(2, b))%5218); 41 System.out.print(yu); 42 } 43 }
9.娜神平衡
代码如下:

1 import java.util.Arrays; 2 import java.util.Scanner; 3 4 public class Main { 5 static int N;// 数据的总个数 6 static int R;// 相差不能超过R 7 static int[] A;// A存放元素的数组 8 static int[] B;// B存放元素的数组 9 static int[] vis;// 数据被使用的状态 10 static int a = 0;// A的元素 11 static int b = 0;// B的元素 12 static int flag = 0;// 结束标志,题目告知答案唯一,所以找到答案后就结束。 13 14 public static void main(String[] args) { 15 Scanner scanner = new Scanner(System.in); 16 int n = scanner.nextInt(); 17 N = n; 18 vis = new int[n]; 19 int r = scanner.nextInt(); 20 R = r; 21 A = new int[n]; 22 B = new int[n]; 23 int[] arr = new int[n]; 24 for (int i = 0; i < n; i++) { 25 arr[i] = scanner.nextInt(); 26 } 27 DFS(arr, 1); 28 } 29 30 // 求和 31 public static int sum(int[] num) { 32 int sum = 0; 33 for (int x : num) { 34 sum += x; 35 } 36 return sum; 37 } 38 39 // 深度搜索 40 public static void DFS(int[] arr, int step) { 41 if (Math.abs(sum(A) - sum(B)) > R) {//不符合题目条件的直接返回结束 42 return; 43 } 44 if (step > N) {//找到答案 45 //对A、B数组进行从小到大的排序 46 Arrays.sort(A, 0, a - 1); 47 Arrays.sort(B, 0, b - 1); 48 //输出结果 49 for (int i = 0; i < a; i++) { 50 System.out.print(A[i] + " "); 51 } 52 System.out.println(); 53 for (int i = 0; i < b; i++) { 54 System.out.print(B[i] + " "); 55 } 56 flag = 1;//修改结束标志 57 return; 58 } 59 //先往A里面放元素,直到放进A不满足条件 A-B的绝对值<r 60 for (int i = 0; i < N; i++) { 61 if (flag == 1) {// 先判断结束标志 62 return; 63 } 64 if (vis[i] == 0) { 65 A[a++] = arr[i]; 66 vis[i] = 1; 67 DFS(arr, step + 1);//放下一个 68 A[--a] = 0; 69 vis[i] = 0; 70 } 71 } 72 73 //放完A后,往B放元素 74 for (int i = 0; i < N; i++) { 75 if (flag == 1) {// 先判断结束标志 76 return; 77 } 78 if (a == 0) {//题目中要求先往A放,所以放入B时先检测A里面有没有元素 79 return; 80 } 81 if (vis[i] == 0) { 82 B[b++] = arr[i]; 83 vis[i] = 1; 84 DFS(arr, step + 1);//放下一个 85 B[--b] = 0; 86 vis[i] = 0; 87 } 88 } 89 } 90 91 }
10.粘木棍
代码如下:

1 import java.util.Arrays; 2 import java.util.Scanner; 3 4 public class Main { 5 6 static int mm; 7 public static void main(String args[]) { 8 Scanner sc=new Scanner(System.in); 9 int N=sc.nextInt(); 10 int M=sc.nextInt(); 11 int[] a=new int[N]; 12 for(int i=0;i<N;i++) { 13 a[i]=sc.nextInt(); 14 //总长度 15 mm+=a[i]; 16 } 17 int[] b=new int[M]; 18 //b 记录每根木棍长度,c记录木棍是否使用 19 fun(a,b,0,N,M); 20 System.out.print(mm); 21 } 22 public static void fun(int[] a,int[] b,int k,int n,int m) { 23 //如果还有木棍 24 if(k<n) { 25 //遍历数组b 26 for(int i=0;i<m;i++) { 27 //暂时将这个木棒加到当前的木棒组上 28 b[i]+=a[k]; 29 //继续往下调用函 30 fun(a,b,k+1,n,m); 31 //在这个木棒组上去下当前木棒,以便在下一木棒组上使用 32 b[i]-=a[k]; 33 } 34 }else {//当木棒全部粘完时 35 //找出当前所有木棒组里最小值和最大值 36 int max=b[0],min=b[0]; 37 for(int i=0;i<m;i++) { 38 if(b[i]>max) { 39 max=b[i]; 40 } 41 if(b[i]<min) { 42 min=b[i]; 43 } 44 } 45 if(max-min<mm) { 46 mm=max-min; 47 } 48 } 49 } 50 }
11.车的放置
代码如下:

1 import java.io.*; 2 3 public class Main { 4 public static void main(String[] args) throws NumberFormatException, IOException { 5 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 6 int n = Integer.parseInt(br.readLine()); 7 Temp996b temp = new Temp996b(n); 8 temp.dfs(1);//从第一行开始摆放 9 System.out.println(temp.ans); 10 } 11 } 12 class Temp996b{ 13 int n; 14 int ans = 1; 15 boolean visited[] = new boolean[9];//表示第几列是否摆放 16 17 public Temp996b(int n) { 18 this.n = n; 19 } 20 21 public void dfs(int step) {//表示棋子应放到第temp行 22 if(step > n) {//递归出口:当前摆放行数超出棋盘总行数 23 return; 24 } 25 for(int i = 1; i <= n; i++) { 26 if(!visited[i]) {//step行的第i列为空 27 visited[i] = true;//已放置 28 ans++; 29 dfs(step + 1);//递归至下一行摆放 30 visited[i] = false;//回溯:将step行重置 31 } 32 } 33 dfs(step + 1);//有空行情况,将step行跳过(不摆放) 34 } 35 }
12.24点:
代码如下:
无。。。
13.最大分解:
代码如下:

1 import java.util.Scanner; 2 3 public class Main { 4 5 public static void main(String[] args){ 6 7 //a0的值 8 Scanner input= new Scanner(System.in); 9 int a0 = input.nextInt(); 10 int[] a = new int[a0]; 11 a[0] = a0; 12 int sum = 0 ; 13 int j = 0; 14 15 //找值。 16 for (int i = a0-1; i >=1 ; i--) { 17 if(a[j]%i==0){ 18 //把数存起来,下标+1. 19 sum += i; 20 j++; 21 a[j] = i; 22 } 23 } 24 System.out.println(sum); 25 26 } 27 28 29 }
14.RP大冒险
代码如下(没看懂,随便写的)

1 import java.util.Scanner; 2 3 public class Main { 4 5 public static void main(String[] args){ 6 7 8 9 int[] a = {0,1,2,3,4,5,6,7,8,9 10 }; 11 int b = new Scanner(System.in).nextInt(); 12 13 System.out.println(a[b]); 14 15 16 } 17 18 19 }
待更新。。。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程