文章目录
A. 星期计算B. 山C. 字符统计D. 最少刷题数E. 求阶乘F. 最大子矩阵G. 数组切分H. 回忆迷宫I. 红绿灯J. 拉箱子个人总结
A. 星期计算
思路解析:
大整数类的应用,计算幂后对其取余。官方给的计算器也能直接计算其值
答案:
取余结果为1,所以答案为7
代码:
package lanqiao;import java.math.BigInteger;//答案:6+1=7public class A_星期计算 {public static void main(String[] args) {// TODO Auto-generated method stubBigInteger num = new BigInteger("20");BigInteger ans = new BigInteger("1");for(int i=1;i<=22;i++) {ans = ans.multiply(num);}System.out.println(ans);System.out.println(ans.mod(new BigInteger("7")));}}
B. 山
思路解析:
因为只是个填空题,可以暴力枚举,判断是否为回文数(字符串翻转和原串相同)以及前n/2是否满足递增
答案:
3138
代码:
package lanqiao;public class B_山 {//答案:3138public static void main(String[] args) {// TODO Auto-generated method stublong ans=0;for(long i=2022;i<=2022222022;i++) {if(check(i)) {ans++;}}System.out.println(ans);}private static boolean check(long i) {//判断是否回文String string = String.valueOf(i);StringBuilder sBuilder = new StringBuilder(string);if(string.compareTo(sBuilder.reverse().toString())==0) { //是回文数for(int j=0;j<string.length()/2;j++) {int pre = Integer.valueOf(string.charAt(j));int aft = Integer.valueOf(string.charAt(j+1));if(aft<pre)return false;}System.out.println(i);return true;}return false;}}
C. 字符统计
思路解析:
在输入的时候,记录出现字符最多的次数,并将每个字符以及其次数用HashMap存储。再次遍历HashMap,将出现次数等于最多的加入到一个TreeSet中,最后TreeSet能维持字典序,输出TreeSet元素为答案
代码:
/** * */package lanqiao;import java.util.HashMap;import java.util.Map;import java.util.Scanner;import java.util.Set;import java.util.TreeSet;public class C_字符统计 {public static void main(String[] args) {Scanner scanner=new Scanner(System.in);String string = scanner.next();Map<Character, Integer> map = new HashMap<>();int ans_count = Integer.MIN_VALUE;for(int i=0;i<string.length();i++) {char c = string.charAt(i);if(map.get(c)==null) {map.put(c, 1);}else {map.put(c, map.get(c)+1);}if(map.get(c)>ans_count) {ans_count=map.get(c);}}Set<Character> ansCharacters = new TreeSet<>();for(Map.Entry<Character, Integer> entry:map.entrySet()) {if(entry.getValue()==ans_count) {ansCharacters.add(entry.getKey());}}for(Character c:ansCharacters) {System.out.print(c);}}}
D. 最少刷题数
思路解析:
采用arr与find两个数组存储N个整数,将find进行sort排序,遍历arr,在find中二分查找arr[i]的位置pos,然后可以计算出小于arr[i]与大于arr[i]的数目之差d,如果不满足小于其的数量多余大于其的数量,则输出find[pos+d/2]-find[pos]+1
代码:
package lanqiao;import java.util.Arrays;import java.util.Scanner;public class D_最少刷题数 {public static void main(String[] args) {Scanner scanner=new Scanner(System.in);int N=scanner.nextInt();int[] arr = new int[N];int[] find = new int[N];for(int i=0;i<N;i++) {int num = scanner.nextInt();arr[i]=num;find[i]=num;}Arrays.sort(find);for(int i=0;i<N;i++) {//在find中查找arr[i]的位置int pos = Arrays.binarySearch(find, arr[i]);//计算其左边的数int less = pos;int more = N-pos-1;if(more>less) { //刷题多的多余刷题少的int d = more-less;int num = find[pos+d/2]-find[pos]+1;System.out.print(num+" ");}else {System.out.print(0+" ");}}}}
E. 求阶乘
思路解析:
个人感觉这道题比较难,想了很久,只知道要想凑个10,就必须要有一个2和5,但是明显在一个阶乘里,因子为2的数量一定多余5的数量,所以计算5的数量,但是感觉代码写出来后,测试一些样例还是不对(欢迎讨论探讨)
代码:
package lanqiao;import java.util.Scanner;public class E_求阶乘 {static int[] rec;//一个2与一个5可以产生一个0;在N的阶乘中,2的数目肯定多余5的数目,所以考虑5的数目就可以public static void main(String[] args) {rec=new int[100000000];Scanner scanner=new Scanner(System.in);long k=scanner.nextLong();int num=5;rec[5]=1;while(k>0) {int count = f(num); //计算num中含有多少个5k-=count;if(k<=0)break;num+=5;}if(k<0) {System.out.println(-1);}else {System.out.println(num);}}private static int f(int num) {if(rec[num]!=0||num<5) {return rec[num];}if(num%5==0) {int res = 1+f(num/5);rec[num]=res;return res;}else {rec[num]=0;return 0;}}}
F. 最大子矩阵
思路解析:
我这里采用的是暴力枚举法,从大到小枚举出最大长于宽,然后枚举每一个左上角顶点,计算该矩阵是否符合要求,维护一个最大面积。但是个人随着测试样例范围变大感觉会超时,可以提前对矩阵元素进行预处理,以降低复杂度
代码:
package lanqiao;import java.util.Scanner;public class F_最大子矩阵 {static int[][] arr;public static void main(String[] args) {Scanner scanner=new Scanner(System.in);int N=scanner.nextInt();int M=scanner.nextInt();arr=new int[N][M];for(int i=0;i<N;i++) {for(int j=0;j<M;j++) {arr[i][j]=scanner.nextInt();}}int limit = scanner.nextInt();int max_are = Integer.MIN_VALUE;for(int i=N;i>0;i--) {for(int j=M;j>0;j--) { // i*j的矩阵for(int x=0;x<=N-i;x++) {for(int y=0;y<=M-j;y++) { //左上角坐标int max = find_max(i,j,x,y);int min = find_min(i,j,x,y);if((max-min)<=limit) {max_are = Math.max(max_are, i*j);//System.out.println(x+" "+y+" "+" "+i+" "+j);//System.out.println(i*j);//return;}}}}}System.out.println(max_are);}private static int find_min(int i, int j, int x, int y) {// TODO //寻找最小值int res = Integer.MAX_VALUE;for(int n=x;n<x+i;n++) {for(int m=y;m<y+j;m++) {res = Math.min(res, arr[n][m]);}}return res;}private static int find_max(int i, int j, int x, int y) {// TODO 寻找最大值int res = Integer.MIN_VALUE;for(int n=x;n<x+i;n++) {for(int m=y;m<y+j;m++) {res = Math.max(res, arr[n][m]);}}return res;}}
G. 数组切分
思路解析:
我才用的是深搜算法遍历,但是看了规模以后,明显感觉会超时,个人感觉可以尝试用备忘录的深搜来遍历,因为遍历过程可能会重复计算子问题,但是比赛时间有限,个人也没时间再去优化了
代码:
/** * */package lanqiao;import java.util.Arrays;import java.util.HashSet;import java.util.Scanner;import java.util.Set;public class G_数组切分 {static boolean[] vis;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int N = scanner.nextInt();int[] arr = new int[N];vis = new boolean[N];for (int i = 0; i < N; i++) {arr[i] = scanner.nextInt();}long ans = DFS(arr, 0);System.out.println(ans);}private static long DFS(int[] arr, int k) {if (k == arr.length-1) {if (check(arr)) {//for(int i=0;i<vis.length;i++) {//System.out.print(vis[i] + " ");//}//System.out.println();return 1;}return 0;}// 当前位置切int res = 0;vis[k] = true;res += DFS(arr, k + 1);// 当前位置不切vis[k] = false;res += DFS(arr, k + 1);return res;}private static boolean check(int[] arr) {// TODO 检查当前切法是否符合规则int len = arr.length;int p = 0;int q = 1;while (q < len) {if (vis[q - 1]) {if (!check_lianxu(arr, p, q)) {return false;}p=q;}q++;}if(!check_lianxu(arr, p, q)) {return false;}return true;}private static boolean check_lianxu(int[] arr, int p, int q) {// TODO 检测数组是否连续p-qint[] arrcopy = new int[q-p];System.arraycopy(arr, p, arrcopy, 0, q-p);Arrays.sort(arrcopy);for(int i=0;i<q-p-1;i++) {if(arrcopy[i+1]-arrcopy[i]!=1) {return false;}}return true;}}
H. 回忆迷宫
时间能力有限,今年难度明显增加,实在没时间去做
I. 红绿灯
时间能力有限,今年难度明显增加,实在没时间去做
J. 拉箱子
时间能力有限,今年难度明显增加,实在没时间去做
个人总结
这次应该是自己大学生涯里面的最后一次蓝桥杯了。
大一,大学里的第一次蓝桥杯是在大一的时候,第一次接触蓝桥杯的时候,感觉是真的很难,很多的算法自己听都没听说过,更别说去用了。当时参加的是C/C++,也是因为疫情在家,所以自己能有充足的时间去学习自己喜欢的技术,沉下心来练习算法题。当时那一届C/C++明显也比较简单,所以自己能做的都做出来了,最终拿了个省二,对于刚进入大学压根没接触过编程的我,在大一能拿到蓝桥杯省二给了我极大的自信。
大二,在大二的时候自己毫不犹豫继续报了蓝桥杯Java,当时也是练了很多题,但是在最后比赛的一个月,由于返校上课时间紧张,当时也作为队长和朋友们参加了其它几个比赛,正好也赶上当时那几个比赛的各种答辩,所以最后一个月练题数几乎为0,等到正式比赛的前一天晚上也才发现自己准考证也没打印,当时也比较慌,晚上睡觉也没睡好,所以第二天比赛个人就很迷,第一道编程题都没做出来,唉,或许万事不可能同时都做到最好吧,最终比赛也只拿到了省二,这次的省二反而让我很遗憾。
大三,课程少了,也没心思再去参加其它比赛,同时也要开始准备考研,但是想到自己大学生涯在蓝桥杯上的遗憾,选择再一次参加蓝桥杯,这一次,拼劲全力,从第6届开始,每一年的真题都来来回回刷了一遍,算法很美课程也跟着刷了一遍,所有例题思路都跟着做了一遍总结。3月月末,我们学校Java组选择退赛的就有2/3,个人感觉这次的压力明显变大,加上疫情,这次又导致线上比赛。。。
最后只能用一句话描述我与蓝桥杯:遇见蓝桥遇见你,不负代码不负卿。蓝桥杯是我大学竞赛的起点,同时也是我竞赛的终点。