蓝桥杯--结束

冲刺题单

基础

一、简单模拟(循环数组日期进制)

(一)日期模拟

知识点

1.把月份写为数组,二月默认为28天。
2.写一个判断闰年的方法,然后循环年份的时候判断并更新二月的天数
3.对于星期数的计算:
int week = x;//x表示当前天数的星期数
week = week % 7 + 1;

1.艺术与蓝球–蓝桥19937

package datasimulation;public class Test5 {//每个月,2月先默认为28天//数组下标从0开始,给monts【0】赋值0static int[] months = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};//汉字笔画数static int[] hz = {13, 1, 2, 3, 5, 4, 4, 2, 2, 2};//判断闰年static boolean isLeapYear(int year){//能整除400 或者 能整除4不能整除100return (year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0));}static void solve(){int ans = 0;//记录打篮球的天数for(int y = 2000; y <= 2024; y++){//重判二月的天数months[2] = isLeapYear(y) ? 29 : 28;for(int m = 1; m <= 12; m++){for(int d = 1; d <= months[m]; d++){int sum = 0;//记录权值//获得每一个数int y1 = y / 1000;int y2 = y / 100 % 10;int y3 = y / 10 % 10;int y4 = y % 10;int m1 = m / 10;int m2 = m % 10;int d1 = d / 10;int d2 = d % 10;sum = hz[y1] + hz[y2] + hz[y3] + hz[y4]+ hz[m1] + hz[m2]+hz[d1] + hz[d2];//判断权值if(sum > 50) ans++;//循环结束条件if(y == 2024 && m == 4 && d == 13){System.out.println(ans);return;//结束}}}}}public static void main(String[] args) {solve();}
}
//答案:3228

2.岁月流转–星期模拟–蓝桥16955

本题就和上面一样,不过多了个星期的问题,应用那两条公式即可。
package datasimulation;public class Test6 {//每个月,2月先默认为28天//数组下标从0开始,给monts【0】赋值0static int[] months = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};//判断闰年static boolean isLeapYear(int year){//能整除400 或者 能整除4不能整除100return (year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0));}//获取1900年12月31日的星期数static int getWeek(int week){//1900年1.1是星期一,那么它前一天是星期日即7months[2] = isLeapYear(1900) ? 29 : 28;for (int m = 1; m <= 12; m++) {for (int d = 1; d <= months[m]; d++) {week = week % 7 + 1;}}return week;}static void solve(){int week = getWeek(7);获取1900年12月31日的星期数int ans = 0;for (int y = 1901; y <= 2000; y++) {months[2] = isLeapYear(y) ? 29 : 28;for (int m = 1; m <= 12; m++) {for (int d = 1; d <= months[m]; d++) {week = week % 7 + 1;if(d == 1 && week == 7) ans++;}}}System.out.println(ans);}public static void main(String[] args) {solve();}
}
//171

3.跑步计划–日期星期模拟–蓝桥17113


public class Main {//每个月,2月先默认为28天//数组下标从0开始,给monts【0】赋值0static int[] months = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};//判断闰年static boolean isLeapYear(int year){//能整除400 或者 能整除4不能整除100return (year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0));}static void solve(){int kl = 0;//跑步的公里数//2023.1.1是星期日int week = 6;months[2] = isLeapYear(2023) ? 29 : 28;for (int m = 1; m <= 12; m++) {for (int d = 1; d <= months[m]; d++) {//计算星期week = week % 7 + 1;//拆分数字int m1 = m / 10;int m2 = m % 10;int d1 = d / 10;int d2 = d % 10;//只要年月日或者星期有1,就跑5千米if(week == 1 || m1 == 1 || m2 == 1 || d1 == 1 || d2 == 1){kl += 5;}else{kl += 1;}}}//输出公里数System.out.println(kl);}public static void main(String[] args) {solve();}
}
//1333

4.一年中的第几天–蓝桥1935

package datasimulation;import java.util.Scanner;public class Test8 {static int[] months = {0,31,28,31,30,31,30,31,31,30,31,30,31};//判断闰年static boolean isLeapYear(int y){return (y % 400 == 0) || ((y % 4 == 0) && (y % 100 != 0));}//主逻辑函数static void solve(int y, int m, int d){int day = 0;//表示第几天//更新2月的天数months[2] = isLeapYear(y) ? 29 : 28;for (int i = 1; i <= 12; i++) {//月份数for (int j = 1; j <= months[i]; j++) {//天数day++;if(i == m && j == d){System.out.println(day);return;//结束循环}}}}public static void main(String[] args) {Scanner sc = new Scanner(System.in);while(true){int y = sc.nextInt();int m = sc.nextInt();int d = sc.nextInt();if(y == 0 && m == 0 && d == 0) break;//结束solve(y, m, d);}}
}
本题出现评测机段错误的原因:
将Scanner写在了while循环中,拿出来即可
因此获得经验:对于一些特定的语句,一定要注意只创建一次即可。

5.回文日期–蓝桥498

注意给定的N小于89991231但是循环的边界不应该是8999,而应该是9999
package datasimulation;import java.util.Scanner;public class Test9 {static boolean flag1 = false;static boolean flag2 = false;static int[] months = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};//判断闰年static boolean isLeapYear(int y) {return (y % 400 == 0) || ((y % 4 == 0) && (y % 100 != 0));}static boolean check(int y, int m, int d) {//获得每一位数int y1 = y / 1000;int y2 = y / 100 % 10;int y3 = y / 10 % 10;int y4 = y % 10;int m1 = m / 10;int m2 = m % 10;int d1 = d / 10;int d2 = d % 10;//判断回文if (flag1 == false) {if (d2 == y1 && d1 == y2 && m2 == y3 && m1 == y4) {flag1 = true;if(m >= 10 && d >= 10){System.out.println(y + "" + m + "" + d);} else if (m >= 10 && d < 10) {System.out.println(y + "" + m + "0" + d);} else if (d >= 10 && m < 10) {System.out.println(y + "0" + m + "" + d);} else if (m < 10 && d < 10) {System.out.println(y + "0" + m + "0" + d);}}}//判断ABABBABA型回文int A = y1;int B = y2;if (flag2 == false) {if (y3 == A && y4 == B && m1 == B && m2 == A && d1 == B && d2 == A) {flag2 = true;if(m >= 10 && d >= 10){System.out.println(y + "" + m + "" + d);} else if (m >= 10 && d < 10) {System.out.println(y + "" + m + "0" + d);} else if (d >= 10 && m < 10) {System.out.println(y + "0" + m + "" + d);} else if (m < 10 && d < 10) {System.out.println(y + "0" + m + "0" + d);}}}//两个都判断结束退出if (flag1 && flag2) {return true;}return false;}static void solve () {Scanner sc = new Scanner(System.in);int N = sc.nextInt();int year = N / 10000;int month = N / 100 % 100;int day = N % 100;//先循环到这个月结束months[2] = isLeapYear(year) ? 29 : 28;for (int d = day + 1; d <= months[month]; d++) {boolean f = check(year, month, d);if(f){return;//结束循环}}//循环到这一年结束months[2] = isLeapYear(year) ? 29 : 28;for (int m = month + 1; m <= 12; m++) {for (int d = 1; d <= months[m]; d++) {boolean f = check(year, m, d );if(f){return;//结束循环}}}for (int y = year + 1; y <= 9999; y++) {months[2] = isLeapYear(y) ? 29 : 28;for (int m = 1; m <= 12; m++) {for (int d = 1; d <= months[m]; d++) {boolean f = check(y, m, d );if(f){return;//结束循环}}}}}public static void main (String[]args){solve();}}
更简便的写法:
data等的使用

6.神奇的闹钟–蓝桥19730


(二)进制转换

知识点

1.1K进制转十进制

K进制转十进制:
对于十六进制,由于它的数字表示范围为0-9,A-Z(或者a-z),在转换时要注意。
因此在赋值存储时,将要转换的进制数使用字符串类型来存储。
由此在进行进制转换前,要先将字符串类型的进制数转为数字。
1.将字符转换为数字值:
利用ascii码来进行转换。
2.将进制数转换为十进制:
horner法则

image-20250303080647318

模板

package jinzhizhuanhuan;public class Test1 {//将字符转为数字static int calc(char c){//大于10的数if(c >= 'a'){//A或者a看题目要求return 10 + (c - 'a');}else {return (c - '0');}}//将给定的字符串转换为10进制static int change(int k, String s){int ans = 0;for (int i = 0; i < s.length(); i++) {ans = ans * k + calc(s.charAt(i));}return ans;}public static void main(String[] args) {System.out.println( change(16,"4e"));//78}
}

题目答案

package jinzhizhuanhuan;
import java.util.Scanner;
public class Test6 {//得到位数static int calc(char c){if(c >= 'A'){return 10 + (c - 'A');}else{return c - '0';}}//k进制转10进制//幂运算转为hornor运算static int change(int k, String s){int ans = 0;for (int i = 0; i < s.length(); i++) {ans = ans * k + calc(s.charAt(i));}return ans;}public static void main(String[] args) {Scanner sc = new Scanner(System.in);int x = sc.nextInt();String s = sc.next();System.out.println(change(x, s));}
}

1.2十进制转K进制–洛谷B3619

**除K取余法**
注意得到所有的余数后要反向排列才是最后的结果。

模板

package jinzhizhuanhuan;public class Test2 {static String change(int x, int k){//把x转为k进制StringBuffer ans = new StringBuffer();while(x != 0){int t = x % k;//除k取余if(t <= 9){//数字部分直接添加ans.append((char)('0' + t));}else{//字母部分从A开始ans.append((char)('A' + (t - 10)));}x = x / k;//更新x}//除K取余后要记得反转return ans.reverse().toString();}//十进制转K进制static void solve(){System.out.println(change(78, 16));}public static void main(String[] args) {solve();}
}

题目答案

import java.util.Scanner;
public class Main {static String change(int x, int k){//除K取余法StringBuffer ans = new StringBuffer();while(x != 0){int t = x % k;//除k取余if(t > 9){//字母部分ans.append((char)('A' + (t - 10)));}else{//数字部分ans.append((char)('0' + t));}x = x / k;//更新x}//除k取余得到的是一个反向的//最后要把它倒回来return ans.reverse().toString();}public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int x = sc.nextInt();System.out.println(change(n, x));}
}

2.穿越时空之门–蓝桥19701

在上面的基础上进行修改即可
还无需考虑16进制的字母
package jinzhizhuanhuan;public class Test3 {//十进制转K进制(不用担心十六进制的字母问题)//除k取余法并求各位数之和static int change(int x, int k){int ans = 0;//记录各位数之和while(x != 0){int t = x % k;//除k取余,k的取值是2和4,那么t的取值小于等于4ans += t;x = x / k;//更新x}return ans;}//主逻辑函数static void solve(){int count = 0;for (int i = 1; i <= 2024; i++) {if(change(i, 2) == change(i, 4))count++;}System.out.println(count);}public static void main(String[] args) {solve();}
}

3.九进制转十进制–蓝桥2095

就是前面模板直接套用就可以
package jinzhizhuanhuan;public class Test4 {static int calc(char c){if(c >= 'A'){return 10 + (c - 'A');}else {//数字return c - '0';}}static int change(int k,String s){int ans = 0;//k进制转10进制//幂运算转换为hornor法则for (int i = 0; i < s.length(); i++) {ans = ans * k + calc(s.charAt(i));}return ans;}public static void main(String[] args) {System.out.println(change(9, "2022"));}
}

(三)枚举

1.好数–蓝桥19709

package meiju;import java.util.Scanner;public class Test1 {static boolean check(int x){int count = 1;//记录奇偶位数while(x != 0){int t = x % 10;if(count % 2 != 0){//奇数位上不能是偶数if(t % 2 == 0){return false;}}if(count % 2 == 0){//偶数位上不能是奇数if(t % 2 != 0){return false;}}x = x / 10;//更新,即去掉最后一位count++;//更新奇偶数位}//循环结束即是好数return true;}static void solve(){Scanner sc = new Scanner(System.in);int n = sc.nextInt();int ans = 0;//记录个数for (int i = 1; i <= n; i++) {if(check(i)){ans++;}}System.out.println(ans);}public static void main(String[] args) {solve();}
}

2.偶串–蓝桥17144

主要涉及HashMap的使用
import java.util.HashMap;
import java.util.Scanner;
public class Main {static int N = 1000010;//定义一个字符数组static HashMap<Character, Integer> charArr = new HashMap<Character, Integer>();//判断是否都为偶数static boolean check(HashMap<Character, Integer> arr){for (int count : charArr.values()) {if (count % 2 != 0) return false;//奇数返回错}return true;}static void solve(){Scanner sc = new Scanner(System.in);String s = sc.next();for (int i = 0; i < s.length(); i++) {char c = s.charAt(i);//如果这个字符 c 已经存在,就获取它的计数,否则默认是 0。charArr.put(c, charArr.getOrDefault(c, 0) + 1);}if(check(charArr)){System.out.println("YES");}else{System.out.println("NO");}}public static void main(String[] args) {solve();}
}

3.幸运数–蓝桥3491

填空题,代码是超时的。。。
import java.util.ArrayList;public class Main {// static int N = 15;//多一点防止奇怪的问题// static boolean check(int x){//     ArrayList<Integer> numArr = new ArrayList<>();//     int count = 0;//记录x的位数//     while(x != 0){//         int t = x % 10;//获得最后一位//         numArr.add(t);//添加到list中,下标从0开始//         x = x / 10;//舍弃最后一位//         count++;//     }//     //先判断是不是偶数位//     if(count % 2 != 0){//         return false;//     }//     //是偶数位//     int mid = count / 2;//     int sum1 = 0;//     int sum2 = 0;//     for (int i = 0; i < mid; i++) {//         sum1 += numArr.get(i);//     }//     for (int i = mid; i < count; i++) {//         sum2 += numArr.get(i);//     }//     //判断前后是否相等//     if (sum1 != sum2){//         return false;//     }//     //最后是偶数位,前后相等//     return true;// }// static void solve(){//     int ans = 0;//2位//     for (int i = 1; i <= 100; i++) {//         if(check(i)) ans++;//     }//4位//     for (int i = 1000; i <= 9999; i++) {//         if(check(i)) ans++;//     }//6位//     for (int i = 100000; i <= 999999; i++) {//         if(check(i)) ans++;//     }//8位//     for (int i = 10000000; i <= 99999999; i++) {//         if(check(i)) ans++;//     }//     System.out.println(ans);// }public static void main(String[] args) {System.out.println(4430091);}
}

4.求和–蓝桥3493

简单的题目要特别注意数值范围和超时。
package meiju;public class Test4 {public static void main(String[] args) {long ans = 0;for (int i = 1; i <= 20230408; i++) {ans += i;}System.out.println(ans);}
}

5.不完整的算式–蓝桥17135

特别注意中英文符号
四种情况:又可大概分为2种
首先判断字符串中是否有+-*/
一、有,找到加减乘除的位置op
1.A被擦掉
0的位置是?,那么A被擦掉
获得B=substring(op,=)
获得C=subString(=)
2.B
op后面的位置是?,那么B被擦掉
获得A=substring(0,op)
获得C=subString(=)
3.C
=后面的位置是?,C被擦掉
获得A=substring(0,op)
获得B=substring(op,=)
二、没有
4.op
找到?的位置,截取出A,B,C即可
package com.mj;
import java.util.Scanner;public class Main{//主逻辑函数static void solve() {Scanner sc = new Scanner(System.in);String s = sc.next();//输入等式//首先判断等式中有无四则运算符号//注意要依次判断int haveOp = s.indexOf('+');if(haveOp == -1) {haveOp = s.indexOf('-');}if(haveOp == -1) {haveOp = s.indexOf('*');}if(haveOp == -1) {haveOp = s.indexOf('/');}//没有,那么获得A,B,C的值if(haveOp == -1) {int op = s.indexOf('?');//op的位置int d = s.indexOf('=');//注意substring包前不包后int A = Integer.parseInt(s.substring(0,op));int B = Integer.parseInt(s.substring(op + 1,d));int C = Integer.parseInt(s.substring(d + 1));if(A + B == C) {System.out.println('+');}else if(A - B == C) {System.out.println('-');}else if(A * B == C) {System.out.println('*');}else if(A / B == C) {System.out.println('/');}return;}//有//A被擦掉if(s.charAt(0) == '?') {int d = s.indexOf('=');int B = Integer.parseInt(s.substring(haveOp + 1, d));int C = Integer.parseInt(s.substring(d + 1));if(s.charAt(haveOp) == '+') {System.out.println(C - B);}else if(s.charAt(haveOp) == '-') {System.out.println(C + B);}else if(s.charAt(haveOp) == '*') {System.out.println(C / B);}else if(s.charAt(haveOp) == '/') {System.out.println(C * B);}return;}//B被擦掉if(s.charAt(haveOp + 1) == '?') {int d = s.indexOf('=');int A = Integer.parseInt(s.substring(0, haveOp));int C = Integer.parseInt(s.substring(d + 1));if(s.charAt(haveOp) == '+') {System.out.println(C - A);}else if(s.charAt(haveOp) == '-') {System.out.println(A - C);}else if(s.charAt(haveOp) == '*') {System.out.println(C / A);}else if(s.charAt(haveOp) == '/') {System.out.println(A / C);}return;}//C被擦掉int d = s.indexOf('=');int A = Integer.parseInt(s.substring(0, haveOp));int B = Integer.parseInt(s.substring(haveOp + 1, d));if(s.charAt(haveOp) == '+') {System.out.println(A + B);}else if(s.charAt(haveOp) == '-') {System.out.println(A - B);}else if(s.charAt(haveOp) == '*') {System.out.println(A * B);}else if(s.charAt(haveOp) == '/') {System.out.println(A / B);}}public static void main(String[] args){solve();}
}

(四)自定义排序

知识点

1.排序:
Arrays.sort 的自定义排序器只接受对象数组。使用整型对象数组(Integer[])
Arrays.sort(数组)
Arrays.sort(数组,开始,结束)//包前不包后
2.自定义比较器:
不理解

自定义排序注意点-CSDN博客

image-20250411104100681

你用的是什么排序方法要求的类型
int[]Arrays.sort(arr)无法使用 Comparator
Integer[]Arrays.sort(arr, cmp)✅ 可以使用 Comparator
ArrayList<T>Collections.sort(list, cmp)✅ 正确

模板

import java.util.Arrays;
import java.util.Comparator;
public class Main {
// 1. 普通数组排序
static Integer[] nums = {3,1,4,1,5,9};
// 2. 对象排序
static class Student {
String name;
int score;
Student(String name, int score) {
this.name = name;
this.score = score;
}
}
public static void main(String[] args) {
// 匿名内部类方式
Arrays.sort(nums, new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return b - a; // 降序
}
});
// 学生数组
Student[] students = {new Student("Alice",90), new
Student("Bob",85)};
// 多级排序
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student a, Student b) {
if(a.score != b.score)
return b.score - a.score; // 分数降序
return a.name.compareTo(b.name); // 姓名升序
}
});
}
}

1.区间排序

https://www.luogu.com.cn/problem/B4041

注意l和r是从1开始得
而数组下标是从0开始的
package com.mj;
import java.util.*;public class Main{
//	static int N = 100010;//主逻辑函数static void solve() {Scanner sc = new Scanner(System.in);int n = sc.nextInt();Integer[] a = new Integer[n];for(int i =  0; i < n; i++) {a[i] = sc.nextInt();}int q = sc.nextInt();while(q != 0) {int l = sc.nextInt() - 1;int r = sc.nextInt() - 1;//包前不包后Arrays.sort(a, l, r + 1);q--;}for(int i =  0; i < n; i++) {System.out.print(a[i] + " ");}}public static void main(String[] args){solve();}
}

2.奇偶排序

https://hydro.ac/d/shallowdream/p/38

对数组进行排序
自定义比较器:
判断奇偶性:
不同:偶数大于奇数
相同:实际数值大小比较
package com.mj;
import java.util.*;public class Main{
//	static int N = 100010;//主逻辑函数static void solve() {Scanner sc = new Scanner(System.in);int n = sc.nextInt();Integer[] num = new Integer[n];for(int i =  0; i < n; i++) {num[i] = sc.nextInt();}Arrays.sort(num, new Comparator<Integer>() {public int compare(Integer a, Integer b) {//判断奇偶性://不同:偶数大于奇数//相同:实际数值大小比较if(a % 2 == b % 2) {//奇偶性相同,实际数值,由小到大return a - b;}else {//不同:偶数大于奇数//a是偶数,返回1,a大于b排后面//a是奇数,返回-1,a小于b排前面return (a % 2 == 0) ? 1 : -1;}}});//for(int i =  0; i < n; i++) {System.out.print(num[i] + " ");}}public static void main(String[] args){solve();}
}
注意:最开始在外面创建数组,创建得很大
而排序是对整个数组进行排序
因此报空指针错误
所以要在里面进行一个创建数组并排序。
还要特别注意,普通数组不能自定义排序
Integer数组对应Arrays.sort
ArrayList数组对应Collections.sort

3.平面最近点对:

https://hydro.ac/d/shallowdream/p/37


package com.mj;
import java.util.*;public class Main{static class zuobiao{int x;int y;zuobiao(int x,int y){this.x = x;this.y = y;}}//主逻辑函数static void solve() {Scanner sc = new Scanner(System.in);int n = sc.nextInt();zuobiao[] arr = new zuobiao[n];//创建对象数组for(int i =  0; i < n; i++) {int x = sc.nextInt();int y = sc.nextInt();zuobiao t = new zuobiao(x,y);arr[i] = t;}//自定义排序Arrays.sort(arr, new Comparator<zuobiao>() {public int compare(zuobiao a, zuobiao b) {int x1 = a.x;int y1 = a.y;int x2 = b.x;int y2 = b.y;//先判断欧几里得距离long s1 = (long)x1 * x1 + (long)y1 * y1;long s2 = (long)x2 * x2 + (long)y2 * y2;if(s1 != s2) {if(s1 < s2) {//降序排序,先排areturn -1;}else {return 1;}}//再判断横坐标if(x1 != x2) {if(x1 < x2) {return -1;//先排a}else {return 1;}}//再判断纵坐标//前面都没有才会运行此处,不if不然没有返回值
//				if(y1 != y2) {if(y1 < y2) {return -1;//先排a}else {return 1;}}});//输出for(int i =  0; i < n; i++) {System.out.println(arr[i].x + " " + arr[i].y);}}public static void main(String[] args){solve();}
}
虽然逻辑没有问题,但是超时了,超时的原因是输入使用Scanner。
所以修改如下。
//改用 BufferedReader + StringTokenizer
package com.mj;
import java.io.*;
import java.util.*;public class Main {static class Point {int x, y;Point(int x, int y) {this.x = x;this.y = y;}}public static void main(String[] args) throws IOException {// 快速输入BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int n = Integer.parseInt(br.readLine());Point[] arr = new Point[n];for (int i = 0; i < n; i++) {StringTokenizer st = new StringTokenizer(br.readLine());int x = Integer.parseInt(st.nextToken());int y = Integer.parseInt(st.nextToken());arr[i] = new Point(x, y);}// 排序Arrays.sort(arr, new Comparator<Point>() {public int compare(Point a, Point b) {long d1 = 1L * a.x * a.x + 1L * a.y * a.y;long d2 = 1L * b.x * b.x + 1L * b.y * b.y;if (d1 != d2) return Long.compare(d1, d2);if (a.x != b.x) return Integer.compare(a.x, b.x);return Integer.compare(a.y, b.y);}});// 快速输出BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));for (int i = 0; i < n; i++) {bw.write(arr[i].x + " " + arr[i].y + "\n");}bw.flush(); // 一定要刷新}
}

4.三国游戏:

https://www.lanqiao.cn/problems/3518/learning

5.拼数:

https://www.luogu.com.cn/problem/P1012

(四)自定义排序

1.蓝桥19723–分布式队列

package datasimulation;import java.util.Scanner;public class Test3 {//计算数组中最小值public static int getMin(int[] arr){int min = arr[0];//最好设为数组中的某个值for (int i = 0; i < arr.length; i++) {if(arr[i] < min){min = arr[i];}}return min;}//主逻辑函数public static void solve(){Scanner sc = new Scanner(System.in);//输入Nint N = sc.nextInt();//创建一个长度为N的数组,数组元素表示的是每个节点数组的长度int[] arr = new int[N];//输入?行数据while(sc.hasNext()){String op = sc.next();if(op.equals("add")){int opNum = sc.nextInt();//主节点数组长度加1arr[0]++;} else if (op.equals("sync")) {int opNum = sc.nextInt();//副节点数组长度加1//!!!特别注意!!!副队列同步主队列,如果在执行这次操作时副队列已经是跟主队列相同了,// 此时再加1并不合理,最高就是跟主队列相同//其实题目的用例有偷偷暗示arr[opNum] = Math.min(arr[opNum] + 1,arr[0]);}else{//输出可见数//其实就是输出arr数组中的最小值--各个节点数组的长度最小值System.out.println(getMin(arr));}}}public static void main(String[] args) {solve();}
}
注意:
1.使用一个数组来描述,数组的元素表示的是每个节点数组的长度,可见数其实就是这个数组中最小的元素。
2.要特别注意观察题目给的样例,其中可能暗藏玄机。
最开始我只通过50%,后来才发现给的用例可能会重复,如果遇到sync只是一味加加,那么副节点数组的长度就会超过主节点,这就不对了。
3.学到了一个sc.hasNext()的使用。因为本题不知道输入的操作个数。
4.特别注意数据的输入格式。

2.蓝桥19709–好数

package datasimulation;import java.util.Scanner;public class Test4 {public static boolean check(int n){int count = 1;//表示奇偶数位int jicount = 0;int oucount = 0;while(n != 0){int t = n % 10;n = n / 10;if(count % 2 == 0 && t % 2 == 0){oucount++;}if(count % 2 != 0 && t % 2 != 0){jicount++;}count++;//下一位}//注意上面循环count多加了1if(jicount + oucount + 1 == count)  return true;else return false;}//主逻辑函数public static void solve(){Scanner sc = new Scanner(System.in);//输入Nint N = sc.nextInt();int count = 0;//记录好数for (int i = 1; i <= N; i++) {if(check(i)) count++;}System.out.println(count);}public static void main(String[] args) {solve();}
}
//判断好数//奇数位不能是偶数,偶数位不能是奇数public static boolean check(int n){int cnt = 1;//位数计数器while(n != 0){int t = n % 10;if(cnt % 2 != 0){//奇数位不能偶数if(t % 2 == 0) return false;}if(cnt % 2 == 0){//偶数位不能是奇数if(t % 2 != 0) return false;}cnt++;//下一位数n = n / 10;}return true;//都结束了返回true}
学到的知识点:
本题使用暴力来做,额我就只想到对于奇数位是奇数的加1,偶数位是偶数的加一,因此要循环全部,效率较低。而且还有一点就是最好的count多加了1。
老师的解法就是奇数位偶数返回错,偶数位奇数返回错。这样提高了效率,也不需要注意太多。

二、前缀和与差分 要求:省二以上会

知识点

1.一维前缀和:s[i]=s[i-1]+a[i]
快速查询区间和。l-r的区间和就是s[r]-s[l-1]2.一维差分:b[i]=a[i]-a[i-1]
差分数组求前缀和是原数组。
快速进行区间修改(加减)。对l-r的元素加上d,只要b[l]+=d,b[r+1]-=d即可。
以及重要的一点:判断序列元素是否相同,即差分数组除了第一项以外的项数均为0,那么原数组一定所有数字相同。

对于二维,画图更好理解

1.二维前缀和
规定的二维前缀和如下:从(1,1))开始到(x,y)所围成的一个子矩阵中的数的和
对于(x1,y1)到(x2,y2)围成的子矩阵的和,计算如下:
s(x2,y2)-x(x2,y1-1)-x(x1-1,y2)+x(x1-1,y1-1)
如何构造前缀和:
s(x,y)=a(x,y)+s(x-1,y)+s(x,y-1)-s(x-1,y-1)
2.二维差分
**前缀和数组求差分后是原数组,原数组求差分后是差分数组。**
**差分数组求前缀和是原数组,原数组求前缀和是前缀和数组。**
一定明确差分数组求前缀和是原数组。
对差分数组b[i][j]求前缀和,
而差分数组求前缀和就是原数组a[i][j],
所以套用前缀和公式,有:
a[i][j]=b[i][j]+a[i][j-1]+a[i-1][j]-a[i-1][j-1]
对其进行移项,就得到差分数组的公式:
b[i][j]=a[i][j]-a[i][j-1]-a[i-1][j]+a[i-1][j-1]
对一个差分数组,对其x1,y1进行修改,相当于对原数组x1,y1到右下角进行修改
b[x1][y1] += d;
b[x2 + 1][y1] -= d;
b[x1][y2+1] -= d;
b[x2+1][y2+1] += d;

1.1蓝桥18437–一维前缀和(模板

主要注意数据的范围,计算极端情况下数据的范围是否超过int。
package com.mj;
import java.util.Scanner;public class Main{static int N = 100010;static int n,q;static int[] a = new int[N];static int[] s = new int[N];//前缀和数组//主逻辑函数static void solve() {Scanner sc = new Scanner(System.in);n = sc.nextInt();q = sc.nextInt();for(int i = 1; i <= n; i++) {a[i] = sc.nextInt();//计算前缀和数组s[i] = s[i - 1] + a[i];}//q组查询for(int i = 0; i < q; i++) {int l = sc.nextInt();int r = sc.nextInt();System.out.println(s[r] - s[l - 1]);}}public static void main(String[] args){solve();}
}

1.2.求和-蓝桥2080

其实也差不多是一道模板题目的变形。但这题就要注意数值范围了,有一个需要为long,其它不知道怎么搞那就都为long吧。防止溢出之类的。
找规律,提取公因数,最终得到每项都是
a[i]*(a[i+1] + …… + a[n])

1.3一维差分–模板–蓝桥18438

模板提。注意数值范围即可。
还要注意输出的格式。
package com.mj;
import java.util.Scanner;public class Main{static int N = 200010;static int n,m;static int[] a = new int[N];static int[] b = new int[N];//差分数组//主逻辑函数static void solve() {Scanner sc = new Scanner(System.in);n = sc.nextInt();m = sc.nextInt();for(int i = 1; i <= n; i++) {a[i] = sc.nextInt();//计算差分数组b[i] = a[i] - a[i - 1];}for(int i = 0; i < m; i ++) {int l = sc.nextInt();int r = sc.nextInt();int d = sc.nextInt();//对l-r的数增加db[l] += d;b[r + 1] -= d;}//对差分数组求前缀和得到原数组for(int i = 1; i <= n; i++) {a[i] = a[i - 1] + b[i];System.out.print(a[i] +" ");}}public static void main(String[] args){solve();}
}

1.4小蓝的操作–利用差分数组判断序列元素是否相等–蓝桥3399

本题主要还是思维的问题。要将操作的问题进行一个转换。
因为是选择区间进行减一操作,且数据保证一定有解。
那么对于差分数组而言,要让除了第一项外的大于0的数都为0,第一项为1。
把这些数加起来就是操作数。注意数值范围:
分析3:数值范围的分析
对于差分数组,若原数组最坏情况下为1 100000 1 100000这么排列,那么差分数组可能有一半的数量为99999,那么n的一半为5*10^4,相乘大于4.5*10^9,大于int的范围。所以ans需要为long类型。
package com.mj;
import java.util.Scanner;public class Main{static int N = 100010;static int n;static long[] a = new long[N];static long[] b = new long[N];//差分数组//主逻辑函数static void solve() {Scanner sc = new Scanner(System.in);n = sc.nextInt();for(int i = 1; i <= n; i++) {a[i] = sc.nextInt();//计算差分数组b[i] = a[i] - a[i - 1];}long ans = 0;//操作数//差分数组第一项为1ans = b[1] - 1;//第一项操作几次变为1for(int i = 2; i <= n; i++) {if(b[i] > 0) {ans += b[i];//b[i]操作几次变为0}}System.out.print(ans);}public static void main(String[] args){solve();}
}

1.5二维前缀和–模板–蓝桥18439

模板提。
主要判断数值范围。
package com.mj;
import java.util.Scanner;public class Main{static int N = 1010;static int n,m,q;static int[][] a = new int[N][N];static int[][] s = new int[N][N];//前缀和数组//主逻辑函数static void solve() {Scanner sc = new Scanner(System.in);n = sc.nextInt();m = sc.nextInt();q = sc.nextInt();//输入数组for(int i = 1; i <= n; i++) {for(int j = 1; j <= m; j++) {a[i][j] = sc.nextInt();//计算前缀和s[i][j] = a[i][j] + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];}}//q组查询for(int i = 0; i < q; i++) {int x1 = sc.nextInt();int y1 = sc.nextInt();int x2 = sc.nextInt();int y2 = sc.nextInt();System.out.println(s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 -1][y1 -1]);}}public static void main(String[] args){solve();}
}

1.6子矩阵修改问题–蓝桥18440

二维差分模板题目
也是注意数值范围即可
package com.mj;
import java.util.Scanner;public class Main{static int N = 1010;static int n,m,q;static int[][] a = new int[N][N];static int[][] b = new int[N][N];//差分数组//主逻辑函数static void solve() {Scanner sc = new Scanner(System.in);n = sc.nextInt();m = sc.nextInt();q = sc.nextInt();//输入数组for(int i = 1; i <= n; i++) {for(int j = 1; j <= m; j++) {a[i][j] = sc.nextInt();//计算差分数组//前缀和s[i][j] = a[i][j] + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];b[i][j] = a[i][j] - a[i - 1][j] - a[i][j - 1] + a[i - 1][j - 1];}}//q组查询for(int i = 0; i < q; i++) {int x1 = sc.nextInt();int y1 = sc.nextInt();int x2 = sc.nextInt();int y2 = sc.nextInt();int d = sc.nextInt();b[x1][y1] += d;b[x2 + 1][y1] -= d;b[x1][y2+1] -= d;b[x2+1][y2+1] += d;}//输出二维数组for(int i = 1; i <= n; i++) {for(int j = 1; j <= m; j++) {//计算差分数组的前缀和a[i][j] = b[i][j] + a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];System.out.print(a[i][j] + " ");}System.out.println();}}public static void main(String[] args){solve();}
}

https://www.lanqiao.cn/problems/18439/learning/

https://www.lanqiao.cn/problems/18438/learning/

https://www.lanqiao.cn/problems/18440/learning/

https://www.lanqiao.cn/problems/19716/learning/

https://www.lanqiao.cn/problems/19703/learning/

https://www.lanqiao.cn/problems/3533/learning/

https://www.lanqiao.cn/problems/3514/learning

三、二分

知识点

二分:
1.序列二分:在序列中查找(不怎么考,会比较难?)
序列二分应用的序列必须是递增或递减,但可以非严格
只要r是mid-1,就对应mid=(l+r+1)/2
2.答案二分:最值
答案二分更重要的是思路,要自己可以二分的点,一般先写暴力,再将其转为二分。
3.浮点数二分:连续性

模板题目

1.1序列二分模板题–蓝桥18492

模板题目
package erfen;import java.util.Scanner;public class Test1 {static int N = 100010;static int n, q;static int[] a = new int[N];//找到等于x的最左边的数的下标static int getL(int l, int r, int x) {while (l < r) {int mid = l + r >> 1;//右移1表示除以2if (a[mid] >= x) r = mid;else l = mid + 1;}if (a[l] == x)return l;//返回下标elsereturn -1;//不存在}//找到等于x的最右边的数的下标static int getR(int l, int r, int x) {while (l < r) {int mid = l + r + 1 >> 1;//右移1表示除以2if (a[mid] <= x) l = mid;else r = mid - 1;}if (a[l] == x)return l;//返回下标elsereturn -1;//不存在}//找到大于等于x的第一个数的下标static int lower_bound(int l, int r, int x) {while (l < r) {int mid = l + r >> 1;//右移1表示除以2if (a[mid] >= x) r = mid;else l = mid + 1;}if (a[l] >= x)return l;//返回下标elsereturn -1;//不存在}//找到大于x的第一个数的下标static int upper_bound(int l, int r, int x) {while (l < r) {int mid = l + r >> 1;//右移1表示除以2if (a[mid] > x) r = mid;else l = mid + 1;}if (a[l] > x)return l;//返回下标elsereturn -1;//不存在}//主逻辑函数static void solve() {Scanner sc = new Scanner(System.in);n = sc.nextInt();q = sc.nextInt();for (int i = 1; i <= n; i++) {a[i] = sc.nextInt();}for (int i = 0; i < q; i++) {int op = sc.nextInt();int l = sc.nextInt();int r = sc.nextInt();int x = sc.nextInt();if (op == 1) {System.out.println(getL(l, r, x));} else if (op == 2) {System.out.println(getR(l, r, x));} else if (op == 3) {System.out.println(lower_bound(l, r, x));} else if (op == 4) {System.out.println(upper_bound(l, r, x));}}}public static void main(String[] args) {solve();}
}

1.2最大通过数–蓝桥3346–前缀和+二分

本题利用了前缀和和二分
思想很重要,首先枚举左边,再在里面枚举右边的通过数。
先写暴力然后就很容易写二分。
注意数值范围

暴力

package erfen;import java.util.Scanner;public class Test2 {static int N = 200010;static int m,n;static long k;static long[] a = new long[N];static long[] b = new long[N];//主逻辑函数static void solve(){Scanner sc = new Scanner(System.in);n = sc.nextInt();m = sc.nextInt();k = sc.nextLong();for (int i = 1; i <= n; i++) {a[i] = sc.nextLong();a[i] = a[i - 1] + a[i];//计算前缀和}for (int i = 1; i <= m; i++) {b[i] = sc.nextLong();b[i] = b[i - 1] + b[i];//计算前缀和}int ans = 0;for (int i = 0; i <= n; i++) {//循环左边if(a[i] > k) break;//a[0]为0,所以无需担心左边为0没有遍历右边long x = k - a[i];//左边可通过i关for (int j = 0; j <= m; j++) {if(x >= b[j]){//右边可通过j关ans = Math.max(ans, i + j);}else{break;}}}System.out.println(ans);}public static void main(String[] args) {solve();}
}

二分

计算前缀和数组,它是递增的,可以应用二分
要二分就要找到单调的趋势,找到可以二分的点。
package erfen;import java.util.Scanner;public class Test2 {static int N = 200010;static int m,n;static long k;static long[] a = new long[N];static long[] b = new long[N];//主逻辑函数static void solve(){Scanner sc = new Scanner(System.in);n = sc.nextInt();m = sc.nextInt();k = sc.nextLong();for (int i = 1; i <= n; i++) {a[i] = sc.nextLong();a[i] = a[i - 1] + a[i];//计算前缀和}for (int i = 1; i <= m; i++) {b[i] = sc.nextLong();b[i] = b[i - 1] + b[i];//计算前缀和}int ans = 0;for (int i = 0; i <= n; i++) {//枚举左边if(a[i] > k) break;//a[0]为0,所以无需担心左边为0没有遍历右边long x = k - a[i];//剩下的//二分第二个山洞,找到大于x的第一个数//因为是找大于x的第一个数,x可能是最后一个即m,所以r的取值要是m+1int l = 0, r = m + 1;while(l < r){int mid = l + r >> 1;if(b[mid] > x) r = mid;else l = mid + 1;}ans = Math.max(ans, i + l - 1);}System.out.println(ans);}public static void main(String[] args) {solve();}
}

1.3答案二分模板–https://hydro.ac/d/shallowdream/p/33

求最小的最大值,这题和后面那道数列分段一样,都是要求一个最值。
这个最值是自己进行枚举来得到的,这是一个重要的思路。
第二个就是本题的k次加一操作转换为了元素要达到max需要消耗多少k值,由此找到最小的max

暴力

package erfen;import java.util.Scanner;public class Test3 {static int N = 100010;static int n;static long k;static int[] a = new int[N];static void solve(){Scanner sc = new Scanner(System.in);n = sc.nextInt();k = sc.nextLong();for (int i = 1; i <= n; i++) {a[i] = sc.nextInt();}//枚举最小值for (int i = 1; i <= 1e14; i++) {long t = k;//每次都要重新初始化for (int j = 1; j <= n; j++) {//循环数组每个元素看能否达到iif(a[j] < i){t = t -(i - a[j]);//a[j]需要(i - a[j])次加一操作才能达到i}//结束后进行判断if(t < 0){//当前数组某个元素不能达到i,那整个数组都不能达到iSystem.out.println(i - 1);return;//结束全部}}}}public static void main(String[] args) {solve();}
}

二分

找到可以二分的点:随着枚举的最大的最小值越大,t的值即剩余的k操作越来越少。

image-20250314104140782

package erfen;import java.util.Scanner;public class Test3 {static int N = 100010;static int n;static long k;static int[] a = new int[N];//static boolean check(long m){long t = k;//每次都要重新初始化for (int j = 1; j <= n; j++) {//循环数组每个元素看能否达到mif(a[j] < m){t = t -(m - a[j]);//a[j]需要(m - a[j])次加一操作才能达到m}//结束后进行判断if(t < 0){//当前数组某个元素不能达到i,那整个数组都不能达到i/*System.out.println(i - 1);*/return false;//结束全部}}//整个循环结束,表示整个数组可以达到mreturn true;}static void solve(){Scanner sc = new Scanner(System.in);n = sc.nextInt();k = sc.nextLong();for (int i = 1; i <= n; i++) {a[i] = sc.nextInt();}//二分最大的最小值long l = 1;long r = (long)1e14;while(l < r){long mid = l + r + 1 >> 1;if(check(mid)) l = mid;//true,表示可以达到mid,但是这个mid不一定是最大的。所以让l=mid。else r = mid - 1;}System.out.println(l);}public static void main(String[] args) {solve();}
}

1.4数列分段

本题的难点在于分段
思路:
1.枚举最小的最大值
2.分段的思想,采用cnt来记录段数,sum来记录当前段的和。

暴力

package erfen;import java.util.Scanner;public class Test4 {static int N = 100010;static int n,m;static int[] a  = new int[N];//判断能否做最小的最大值static boolean check(int x){int sum = 0;//记录当前段和int cnt = 1;//记录段数,最小也为1for (int i = 1; i <= n; i++) {if(sum + a[i] <= x){//当前段还可以继续加sum = sum + a[i];}else{sum = a[i];//另开一段cnt++;//段数加一}}return cnt <= m;//只有cnt大于m,才说明这个x不是最小的最大值//可以等于是因为元素可能较小,m给的大。}//主逻辑函数static void solve(){Scanner sc = new Scanner(System.in);n = sc.nextInt();m = sc.nextInt();for (int i = 1; i <= n; i++) {a[i] = sc.nextInt();}//枚举最小的最大值for (int i = 1; i <= 1e9; i++) {if(check(i)) {System.out.println(i);return;//结束}}}public static void main(String[] args) {solve();}
}

二分

package erfen;import java.util.Scanner;public class Test4 {static int N = 100010;static int n,m;static int[] a  = new int[N];//判断能否做最小的最大值static boolean check(int x){int sum = 0;//记录当前段和int cnt = 1;//记录段数,最小也为1for (int i = 1; i <= n; i++) {if(a[i] > x) return false;if(sum + a[i] <= x){//当前段还可以继续加sum = sum + a[i];}else{sum = a[i];//另开一段cnt++;//段数加一}}return cnt <= m;//只有cnt大于m,才说明这个x不是最小的最大值//可以等于是因为元素可能较小,m给的大。}//主逻辑函数static void solve(){Scanner sc = new Scanner(System.in);n = sc.nextInt();m = sc.nextInt();for (int i = 1; i <= n; i++) {a[i] = sc.nextInt();}//二分最小的最大值//随着i的增大,cnt越来越小。int l = 1,r = (int)1e9;while(l < r){int mid = l + r >> 1;if(check(mid)) r = mid;else l = mid + 1;}System.out.println(l);}public static void main(String[] args) {solve();}
}

练习题

1.求阶乘–蓝桥2145

求末尾恰好有几个0。
思路:
只有2*5才可以得到10。
而且N!中,2的数量一定大于5的数量,所以要统计有多少个5,就可以知道有多少个0。
统计5就统计5的倍数,而对于一些特殊的数25,125,里面不止包含1个5。
对于N,只要一直除5,就可以得到5的数量了。这就是本题的第二个难点。要注意可以二分的点,判断大于小于要灵活变通,题目已经有了提示:这样的N不存在输出-1,就要注意判断

暴力

import java.util.Scanner;public class main {static long k;//判断static boolean check(long x){long count = 0;//统计0的数量while(x != 0){count += x / 5;x = x / 5;}if(count == k) return true;else return false;}static void solve(){Scanner sc = new Scanner(System.in);k = sc.nextLong();//枚举nfor (long i = 1; i <= (long)1e18; i++) {if(check(i)){System.out.println(i);return;//结束循环}}System.out.println(-1);//不存在输出-1}public static void main(String[] args) {solve();}
}
import java.util.Scanner;public class main {static long k;//判断static long getCount(long x){long count = 0;//统计0的数量while(x != 0){count += x / 5;x = x / 5;}return count;}static void solve(){Scanner sc = new Scanner(System.in);k = sc.nextLong();//二分long l = 1, r = Long.MAX_VALUE - 1;//这里r不减1的话,l+r第一步就溢出了while (l < r){long mid = l + r >> 1;long count = getCount(mid);if(count >= k) r = mid;else l = mid + 1;}if(getCount(l) == k) System.out.println(l);else{System.out.println(-1);//不存在输出-1}}public static void main(String[] args) {solve();}
}

搜索

一、回溯法+二进制枚举 要求:省一会

1.递归实现排列型枚举

https://www.lanqiao.cn/problems/19684/learning/

package huisu;
//递归实现排列型枚举
//n 个正整数排成一行后随机打乱顺序,按字典序输出所有不同的方案。
//输入一行,包含一个正整数n
//输出n! 行,每一行为一种方案。字典序较小的先输出。import java.util.Scanner;//对于暴力做法,对于一个数就是一次循环,每次循环还要判断数字是否被上一层选中
//每一次的所有数选完并输出后,要让数字变回未被选中状态,进行下一次的选择
public class Test1 {//记录数字是否被选中static boolean[] st = new boolean[10];//用数组记录排列的数据static int[] path = new int[10];static int n;//回溯static void dfs(int u){//u表示的是这是第几个数的选择,本题我们把数的选择转移到数组中if(u > n){//所有的数字选完了,输出for (int i = 1; i <= n; i++) {System.out.print(path[i]);}//换行System.out.println();}//每一次的选择for (int i = 1; i <= n; i++) {//判断这个数是否被选过if(st[i]) continue;//没被选就选中它,并记下st[i] = true;path[u] = i;//选择下一个数dfs(u + 1);//回溯st[i] = false;}}//主逻辑函数public static void solve(){Scanner sc = new Scanner(System.in);//输入nn = sc.nextInt();//输出dfs(1);}public static void main(String[] args) {solve();}
}
package com.mj;
import java.util.*;public class Main{//记录数字是否被选中static boolean[] st = new boolean[10];//用数组记录排列的数据static int[] path = new int[10];static int n;//static void dfs(int u) {if(u > n) {//递归边界,输出for(int i = 1;i <= n; i++) {System.out.print(path[i] + " ");}System.out.println();//换行}//每一次的选择for(int i = 1;i <= n; i++) {//判断是否被选过if(st[i]) continue;st[i] = true;//没备选就选path[u] = i;//记下dfs(u + 1);//下一格数st[i] = false;//回溯}}//主逻辑函数static void solve() {Scanner sc = new Scanner(System.in);n = sc.nextInt();//输出dfsdfs(1);}public static void main(String[] args){solve();}
}

1.2带分数–蓝桥208

思路,1-9出现且只出现1次,进行9的全排列,把9个数的所有组合排列出来,再把加号和除号放进去,看看哪些符合条件
package com.mj;
import java.util.*;public class Main{//记录数字是否被选中static boolean[] st = new boolean[15];//用数组记录排列的数据static int[] path = new int[15];static int n;static int ans;//static void check(String s) {for(int i = 1; i <= 7; i++) {//加号可以放置的位置for(int j = i + 1; j <= 8; j++) {//除以号可以放置的位置int A = Integer.parseInt(s.substring(0,i));int B = Integer.parseInt(s.substring(i,j));int C = Integer.parseInt(s.substring(j));if (C != 0 && A + (double)B / C == n) {ans++;}}}}static void dfs(int u) {if(u > 9) {//递归边界,9个数全排列完毕StringBuilder sb = new StringBuilder();for (int i = 1; i <= 9; i++) {sb.append(path[i]);}String s = sb.toString();check(s);}//每一次的选择for(int i = 1;i <= 9; i++) {//判断是否被选过if(st[i]) continue;st[i] = true;//没备选就选path[u] = i;//记下dfs(u + 1);//下一格数st[i] = false;//回溯}}//主逻辑函数static void solve() {Scanner sc = new Scanner(System.in);n = sc.nextInt();//dfs(1);System.out.print(ans);}public static void main(String[] args){solve();}
}

2.递归实现指数型的枚举

https://www.lanqiao.cn/problems/19685/learning/


import java.util.Scanner;public class Main {static int n;static int[] st = new int[20];//记录选与不选//递归函数static void dfs(int u){if(u > n){//数都选与不选完了//输出for (int i = 1; i <= n; i++) {if(st[i] == 1) System.out.print(i + " ");}//换行System.out.println();//返回return;}for (int i = 0; i <= 1; i++) {//0表示不选,1表示选st[u] = i;dfs(u + 1);//下一个数字}}//主逻辑函数public static void solve(){Scanner sc = new Scanner(System.in);//输入nn = sc.nextInt();dfs(1);}public static void main(String[] args) {solve();}
}
package huisu;import java.util.Scanner;public class Test2 {static int n;static int[] st = new int[20];//记录选与不选//递归函数static void dfs(int u){if(u > n){//数都选与不选完了//输出for (int i = 1; i <= n; i++) {if(st[i] == 1) System.out.print(i + " ");}//换行System.out.println();//返回return;}/*for (int i = 0; i <= 1; i++) {//0表示不选,1表示选st[u] = i;dfs(u + 1);//下一个数字}*/st[u] = 0;dfs(u + 1);st[u] = 1;dfs(u + 1);}//主逻辑函数public static void solve(){Scanner sc = new Scanner(System.in);//输入nn = sc.nextInt();dfs(1);}public static void main(String[] args) {solve();}
}

3.递归实现组合型枚举

https://www.lanqiao.cn/problems/19686/learning/

思路:每个数选与不选,只要等于3了,就输出结果;
//
额,我的思路根本写不出题解,也不是很对。
一定要注意审题和看样例了解题目啊
输出字典序,并且数字不重复!
所以就按照m个数字来,每次每个数字都循环(1->n),但由于不重复且递增,所以对于下一个数,是dfs(u + 1,i + 1)

import java.util.Scanner;public class Main {static int n,m;static int[] st = new int[20];//记录选与不选//递归函数static void dfs(int u,int start){if(u > m){for (int i = 1; i <= m; i++) {System.out.print(st[i] + " ");}System.out.println();return;}for (int i = start; i <= n; i++) {st[u] = i;dfs(u + 1,i + 1);// 下一个数,保证是递增不重复的}}//主逻辑函数public static void solve(){Scanner sc = new Scanner(System.in);//输入n,mn = sc.nextInt();m = sc.nextInt();dfs(1,1);//从第一个位置,1开始}public static void main(String[] args) {solve();}
}

4.蛋糕的美味值

https://www.lanqiao.cn/problems/8664/learning

思路:其实和第二题差不多,每次都是选和不选,到最后u>n时候,就循环计算sum,判断是否大于k,不是的话判断这些小于k的sum中最大的值。
package huisu;
import java.util.Scanner;
public class Test5 {static int n,k;//记录蛋糕static int[] taste = new int[25];//记录选择static int[] st = new int[25];static int Max = 0;//递归计算蛋糕的最大美味值public static void dfs(int u){if(u > n){int sum = 0;for (int i = 1; i <= n; i++) {if(st[i] == 1)sum = sum + taste[i];}if(sum < k){Max = Math.max(Max,sum);}return;}for (int i = 0; i <= 1; i++) {st[u] = i;dfs(u + 1);}}public static void solve(){Scanner sc = new Scanner(System.in);n = sc.nextInt();k = sc.nextInt();for (int i = 1; i <= n; i++) {taste[i] = sc.nextInt();}dfs(1);System.out.println(Max);}public static void main(String[] args) {solve();}
}

5.N皇后问题

https://www.lanqiao.cn/problems/1508/learning/

难点在于如何使得不在同一排,同一列,与棋盘边框成45度角的斜线。
把棋盘二维问题转换为一维数组的问题
对每列进行查找,找到位置后进行下一列的选择。就避免了二维问题。
这个与棋盘边框成45度角的斜线。就要找规律了。。。要注意数值范围
package huisu;import java.util.Scanner;public class Test6 {static int n;static int ans;static boolean[] col = new boolean[30];static boolean[] zhu = new boolean[30];static boolean[] fu = new boolean[30];public static void dfs(int u){if(u > n){ans++;return;}//u表示第u行//循环的i表示第几列for (int i = 1; i <= n; i++) {//首先判断//不在同一排,同一列,与棋盘边框成45度角的斜线。if(col[i] || zhu[n - i + u] || fu[u + i]) continue;//选择col[i] = true;zhu[n - i + u] = true;fu[u + i] = true;dfs(u + 1);//下一行//回溯,释放位置col[i] = false;zhu[n - i + u] = false;fu[u + i] = false;}}public static void solve(){Scanner sc = new Scanner(System.in);n = sc.nextInt();dfs(1);//从第一行开始System.out.println(ans);}public static void main(String[] args) {solve();}
}

6.五子棋对弈

https://www.lanqiao.cn/problems/19694/learning/

思路是对白棋进行递归判断
每次对每个格子都是选与不选,直至25个格子全部选完。
选完之后判断白棋的个数是不是13个
是的话再判断是否为平局。
平局就是排除掉横竖对角线,主副对角线的总和为0或5的。
package huisu;public class Test7 {static int[] st = new int[30];static int[][] qi = new int[10][10];static int ans;//判断平局public static boolean check(){int k = 1;//1表示白棋,0表示黑棋//那么横竖和对角线的sum不能是0或者5//放到二维数组中更好计算判断for (int i = 1; i <= 5; i++) {for (int j = 1; j <= 5; j++) {qi[i][j] = st[k];k++;}}//判断横竖int[] row = new int[6];int[] col = new int[6];for (int i = 1; i <= 5; i++) {for (int j = 1; j <= 5; j++) {row[i] += qi[i][j];col[i] += qi[j][i];}}for (int i = 1; i <= 5; i++) {if(row[i] == 5 || row[i] == 0 || col[i] == 5 || col[i] == 0)return false;}//判断主副对角线int zhu = 0;int fu = 0;for (int i = 1; i <= 5; i++) {zhu += qi[i][i];fu += qi[i][6 - i];}if(zhu == 5 || zhu == 0 || fu == 5 || fu == 0)return false;//都判断完return true;}//递归函数public static void dfs(int u){if (u > 25){int count = 0;//判断白棋是否有13颗for (int i = 1; i <= 25; i++) {if(st[i] == 1)count++;}if(count == 13){//有13颗,那黑棋12颗//接下来就判断是否平局if(check())ans++;}//返回return;}//u表示每一格子for (int i = 0; i <= 1; i++) {st[u] = i;dfs(u + 1);//下一格}}public static void solve(){dfs(1);//对白棋进行选择System.out.println(ans);}public static void main(String[] args) {solve();}
}
在主副对角线的计算那里/*for (int i = 1; i <= 5; i++) {for (int j = 1; j <= 5; j++) {zhu += qi[i][i];fu += qi[i][5 - i + 1];}}*/
刚开始这么计算,是错误的,我重复计算了。呃呃呃。
二维数组还需要学。。。。

7.宝塔

https://www.lanqiao.cn/problems/20111/learning/


8.数字接龙

https://www.lanqiao.cn/problems/19712/learning/


java知识点

1.Java数组默认值
在Java中,当数组被定义但未被显式初始化时,数组元素会自动赋予默认值。不同数据类型的数组有不同的默认值。
整型数组默认值
对于整型数组(如byte、short、int、long),默认值为0。例如:
int[] intArray = new int[5];
System.out.println(intArray[0]); // 输出:0
无论是byte、short、int还是long,其默认值均为0
2.最大值:
Long.MAX_VALUE
在二分中可能会使用,计算mid时要注意溢出问题,l=1的话一般要减一操作。

蓝桥杯就这样子了,一边学一边玩了一个月,感觉明天就是寄了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/77589.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

13、nRF52xx蓝牙学习(GPIOTE组件方式的任务配置)

下面再来探讨下驱动库如何实现任务的配置&#xff0c;驱动库的实现步骤应该和寄存器方式对应&#xff0c;关 键点就是如何调用驱动库的函数。 本例里同样的对比寄存器方式编写两路的 GPOITE 任务输出&#xff0c;一路配置为输出翻转&#xff0c;一路设 置为输出低电平。和 …

Java的基本语法(1)

一、运算符和表达式 举例说明什么是运算符&#xff0c;什么是表达式&#xff1a; int a 1; int b 2; int c a b; 在这个例子当中&#xff0c;是运算符&#xff0c;并且是算术运算符 ab是表达式&#xff0c;因为是运算符&#xff0c;所以ab是算术表达式 1.1算术运算符 …

C++学习之密码学知识

目录 1.文档介绍 2.知识点概述 3.项目准备 4.序列化介绍 5.项目中基础组件介绍 6.基础模块在项目中作用 7.项目中其他模块介绍 8.加密三要素 9.对称加密和非堆成加密 10.对称和非对称加密特点 11.堆成加密算法des 12.des对称加密算法 13.对称加密算法aes 14.知识点…

安装vllm

ubuntu 22.04, RTX3080, cuda 12.1, cudnn 8.9.7&#xff0c;cuda和cudnn的安装参考&#xff1a;https://blog.csdn.net/m0_52111823/article/details/147154526?spm1001.2014.3001.5501。 查看版本对应关系&#xff0c;下载12.1对应的whl包&#xff0c;https://github.com/vl…

【WPF】自定义控件:ShellEditControl-同列单元格编辑支持文本框、下拉框和弹窗

需要实现表格同一列&#xff0c;单元格可以使用文本框直接输入编辑、下拉框选择和弹窗&#xff0c;文本框只能输入数字&#xff0c;弹窗中的数据是若干位的二进制值。 本文提供了两种实现单元格编辑状态下&#xff0c;不同编辑控件的方法&#xff1a; 1、DataTrigger控制控件的…

Gson、Fastjson 和 Jackson 对比解析

目录 1. Gson (Google) 基本介绍&#xff1a; 核心功能&#xff1a; 特点&#xff1a; 使用场景&#xff1a; 2. Fastjson (Alibaba) 基本介绍&#xff1a; 核心功能&#xff1a; 特点&#xff1a; 使用场景&#xff1a; 3. Jackson 基本介绍&#xff1a; 核心功能…

浅谈微信视频号推荐算法

这次可能会稍微有点干货&#xff0c;但保证不晦涩~ 一、算法推荐的本质&#xff1a;猜你喜欢 vs 社交绑架​ 视频号的推荐系统本质上在做两件事&#xff1a; ​预测你的兴趣​&#xff1a;通过你的浏览、点赞、评论、分享等行为&#xff0c;分析你的偏好。​满足社交需求​&…

halcon模板匹配(一)create_shape_model_xld

目录 一、提取刹车盘孔洞轮廓二、形状模板的创建-设置-训练-查找三、找到亮的圆孔四、获得匹配结果五、使用use_polarity进行模板匹配六、计算四个圆对应的矩形框七、创建四个圆对应的模板并查找一、提取刹车盘孔洞轮廓 小技巧总结,使用boundary 函数提取区域边界,在边界范围…

day26图像处理OpenCV

文章目录 一、OpenCV1.介绍2.下载3.图像的表示4.图像的基本操作4.1图片读取或创建4.1.1读取4.1.2创建 4.2创建窗口4.3显示图片4.3.1设置读取的图片4.3.2设置显示多久4.3.3释放 4.4.保存图片4.5图片切片&#xff08;剪裁&#xff09;4.6图片大小调节 5.在图像中绘值5.1绘制直线5…

零基础开始学习鸿蒙开发-智能家居APP离线版介绍

目录 1.我的小屋 2.查找设备 3.个人主页 前言 好久不发博文了&#xff0c;最近都忙于面试&#xff0c;忙于找工作&#xff0c;这段时间终于找到工作了。我对鸿蒙开发的激情依然没有减退&#xff0c;前几天做了一个鸿蒙的APP&#xff0c;现在给大家分享一下&#xff01; 具体…

C++的*了又*

先看下面一段代码 class HeapWord {friend class VMStructs;private:char *i; };主函数 #include "HeapWord.hpp" int main() {HeapWord *heapword new HeapWord();HeapWord *p new HeapWord();HeapWord **p1 new HeapWord *();heapword 3;*(HeapWord **)p he…

yolov8在windows系统的C++版本的onnxruntime部署方法

1.各个软件的的环境需要保持在统一的版本。 onnxruntime需要和cuda的版本对应上,版本号:onnxruntime-win-x64-gpu-1.18.1 ,链接: NVIDIA - CUDA | onnxruntime cuda:本机显卡支持的版本,cuda11.7,链接:CUDA Toolkit Archive | NVIDIA Developer cudnn:需要对应到cud…

js chrome 插件,下载微博视频

修改说明&#xff1a; 代码资源&#xff0c;免积分下载 起因&#xff0c; 目的: 最初是想下载微博上的NBA视频&#xff0c;因为在看网页上看视频很不方便&#xff0c;快进一次是10秒&#xff0c;而本地 VLC 播放器&#xff0c;快进一次是5秒。另外我还想做点视频剪辑。 对比…

【vue3】@click函数传动态变量参数

根据java的学习&#xff0c;摸索了一下vue3 函数传参的方式。以此作为记录。有更好的其它方式&#xff0c;可以评论区补充。 <script> const tmpref(); </script><button click"tmpFunction(传递参数:tmp)">按钮</button> // 直接【字符串…

jmeter 集成ZAP进行接口测试中的安全扫描 实现方案

以下是将 JMeter 集成 ZAP(OWASP Zed Attack Proxy)进行接口测试中安全扫描的实现方案: 1. 环境准备 JMeter 安装:从 JMeter 官方网站(https://jmeter.apache.org/download_jmeter.cgi)下载并安装 JMeter,确保其版本稳定。ZAP 安装:从 ZAP 官方网站(https://www.zapr…

全能格式转换器v16.3.0.159绿色便携版

前言 全能格式转换器具有音视频格式转换、合并视频、压缩视频、录制视频、下载视频、DVD刻录等功能。以超快的转换速度及强大的功能在国外名声大噪&#xff0c;转换速度是市面同类产品的30倍&#xff0c;操作简便&#xff0c;支持158种视频格式无损转换&#xff0c;批量转换高…

【基于开源insightface的人脸检测,人脸识别初步测试】

简介 InsightFace是一个基于深度学习的开源人脸识别项目,由蚂蚁金服的深度学习团队开发。该项目提供了人脸检测、人脸特征提取、人脸识别等功能,支持多种操作系统和深度学习框架。本文将详细介绍如何在Ubuntu系统上安装和实战InsightFace项目。 目前github有非常多的人脸识…

设计一个简单的权限管理系统

针对大规模服务器集群的权限管理系统设计&#xff0c;需结合 角色分层、最小权限原则 和 动态权限控制 来实现安全高效的权限管理。以下是分阶段设计方案&#xff1a; 一、核心设计思路 基于角色的访问控制&#xff08;RBAC&#xff09; 定义角色层级&#xff08;如董事长 >…

使用 nano 文本编辑器修改 ~/.bashrc 文件与一些快捷键

目录 使用 nano 编辑器保存并关闭文件使用 sed 命令直接修改文件验证更改 如果你正在使用 nano 文本编辑器来修改 ~/.bashrc 文件&#xff0c;以下是保存并关闭文件的具体步骤&#xff1a; 使用 nano 编辑器保存并关闭文件 打开 ~/.bashrc 文件 在终端中运行以下命令&#xf…

spm12_fMRI 2*4混合方差分析 Flexible factorial 对比矩阵

实验设计&#xff1a;2*4被试内设计 分析模型&#xff1a;spm 二阶分析中的 Flexible factorial 问题&#xff1a;Flexible factorial交互作用对比矩阵如何编写&#xff1f; 老师&#xff1a;deepseek老师【大神们看看这个矩阵是否可以如下编写&#xff1f;】 以下是来自de…