• 【蓝桥杯 第十五届模拟赛 Java B组】训练题(A - I)


     目录

    A、求全是字母的最小十六进制数

    B、Excel表格组合

    C、求满足条件的日期

    D、 取数字 - 二分

    (1)暴力

    (2)二分

    E、最大连通块 - bfs

    F、哪一天?

    G、信号覆盖 - bfs

    (1)bfs(60%)

    (2)暴力

    H、清理水域 - 暴力(弱智版) 可以差分

    I、滑行 - dfs + dp

    (1)dfs(30%)

    (2)dp+dfs(100%) 


    A、求全是字母的最小十六进制数

    请找到一个大于2022的最小数,该数转换为十六进制后,所有数位(不含前导0)都为字母(A到F),请计算出这个数的十进制。

    思路:

    最小的全是字母的数肯定是全是a的, 从2023开始逐个循环转十六进制判断即可

    答案:2730

    1. import java.util.*;
    2. public class abc {
    3. public static void main(String[] args)
    4. {
    5. Scanner sc=new Scanner(System.in);
    6. int n=2023;
    7. while(true)
    8. {
    9. String s=Integer.toHexString(n);
    10. if(ck(s)==true) break;
    11. n++;
    12. }
    13. System.out.print(n);
    14. }
    15. public static boolean ck(String s)
    16. {
    17. for(char c:s.toCharArray())
    18. {
    19. if(c<'a'||c>'f') return false;
    20. }
    21. return true;
    22. }
    23. }

    B、Excel表格组合

    在Excel中,列的名称使用英文字母组合,前26列用一个字母,依次为A到Z,接下来26*26列使用两个字母的组合,依次为AA到ZZ,求第2022列的名称是什么?

    思路:

    已知单个字母和双字母组合共26+26*26=702,而三个字母组合有26*26*26=17576,因此第2022列名称为三个字母的组合

    三重暴力算2022列的值,答案为:BYT

    1. import java.util.*;
    2. public class abc {
    3. public static void main(String[] args)
    4. {
    5. Scanner sc=new Scanner(System.in);
    6. int beg=702;
    7. for(int i=0;i<26;i++)
    8. for(int j=0;j<26;j++)
    9. for(int k=0;k<26;k++)
    10. {
    11. beg++;
    12. if(beg==2022)
    13. {
    14. char a=(char)('A'+i),b=(char)('A'+j),c=(char)('A'+k);
    15. System.out.print(a+" "+b+" "+c);
    16. break;
    17. }
    18. }
    19. }
    20. }

    C、求满足条件的日期

    对一个日期,我们可以计算出年份的各个数位上的数字之和,也可以分别计算月和日的各位数字之和。请问从1900年1月1日至9999年12月31日,总共有多少天,年份的数位数字之和=月的数位之和+日的数位之和。

    例如:2022年11月13日满足要求,因为6=2+4

    请求出满足条件的日期总数量

    思路:

    数组记录1——12月每一个月的天数,注意闰年2月为29天,然后三重暴力循环计算即可

    答案:70910

    1. import java.util.*;
    2. public class abc {
    3. public static void main(String[] args)
    4. {
    5. Scanner sc=new Scanner(System.in);
    6. int res=0;
    7. int[] a= {0,31,28,31,30,31,30,31,31,30,31,30,31};
    8. for(int i=1900;i<=9999;i++)
    9. {
    10. String y=String.valueOf(i);
    11. for(int j=1;j<=12;j++)
    12. {
    13. if(i%400==0||(i%4==0&&i%100!=0)) a[2]=29;
    14. else a[2]=28;
    15. String m=String.valueOf(j);
    16. for(int k=1;k<=a[j];k++)
    17. {
    18. String d=String.valueOf(k);
    19. if(ck(y,m,d)) res++;
    20. }
    21. }
    22. }
    23. System.out.print(res);
    24. }
    25. public static boolean ck(String y,String m,String d)
    26. {
    27. int yy=0,mm_dd=0;
    28. for(char c:y.toCharArray()) yy+=c-'0';
    29. for(char c:m.toCharArray()) mm_dd+=c-'0';
    30. for(char c:d.toCharArray()) mm_dd+=c-'0';
    31. if(yy==mm_dd) return true;
    32. return false;
    33. }

    D、 取数字 - 二分

    小蓝有30个数,分别为:99,22,51,63,72,61,20,88,40,21,63,30,11,18,99,12,93,16,7,53,64,9,28,84,34,96,52,82,51,77

    小蓝可以从这些数中取出两个序号不同的数,共30*29/2=435种取法

    请问这435种取法中,有多少种取法取出的两个数乘积大于等于2022?

    思路:

    直接暴力枚举,二分优化,答案是:189

    (1)暴力

    1. public class Main4 {
    2. public static void main(String[] args) {
    3. int res=0;
    4. int[] a={99, 22, 51, 63, 72, 61, 20, 88, 40, 21, 63, 30, 11, 18, 99, 12, 93, 16, 7, 53, 64, 9, 28, 84, 34, 96, 52, 82, 51, 77};
    5. for(int i=0;i<30;i++)
    6. for(int j=i+1;j<30;j++ )
    7. if(a[i]*a[j]>=2022) res++;
    8. System.out.println(res);
    9. }
    10. }

    (2)二分

    1. import java.util.*;
    2. public class abc {
    3. public static void main(String[] args)
    4. {
    5. Scanner sc=new Scanner(System.in);
    6. int res=0;
    7. int[] a= {99, 22, 51, 63, 72, 61, 20, 88, 40, 21, 63, 30, 11, 18, 99, 12, 93, 16, 7, 53, 64, 9, 28, 84, 34, 96, 52, 82, 51, 77};
    8. Arrays.sort(a);
    9. for(int i=0;i1;i++) //最后一个数没有后续配对的
    10. {
    11. int target=(int)Math.ceil(2022*1.0/a[i]);
    12. int idx=binary(a,target,i+1,a.length-1); //在【i+1,n-1】区间找防止重复
    13. if(2022/a[i]>a[idx]) continue;
    14. res+=a.length-idx;
    15. }
    16. System.out.print(res);
    17. }
    18. public static int binary(int[] a,int target,int l,int r)
    19. {
    20. while(l
    21. {
    22. int mid=l+r>>1;
    23. if(a[mid]>=target) r=mid;
    24. else l=mid+1;
    25. }
    26. return r;
    27. }
    28. }

    E、最大连通块 - bfs

    小蓝有一个 30 行 60 列的数字矩阵,矩阵中的每个数都是 0 或 1 。  

    1. 110010000011111110101001001001101010111011011011101001111110
    2. 010000000001010001101100000010010110001111100010101100011110
    3. 001011101000100011111111111010000010010101010111001000010100
    4. 101100001101011101101011011001000110111111010000000110110000
    5. 010101100100010000111000100111100110001110111101010011001011
    6. 010011011010011110111101111001001001010111110001101000100011
    7. 101001011000110100001101011000000110110110100100110111101011
    8. 101111000000101000111001100010110000100110001001000101011001
    9. 001110111010001011110000001111100001010101001110011010101110
    10. 001010101000110001011111001010111111100110000011011111101010
    11. 011111100011001110100101001011110011000101011000100111001011
    12. 011010001101011110011011111010111110010100101000110111010110
    13. 001110000111100100101110001011101010001100010111110111011011
    14. 111100001000001100010110101100111001001111100100110000001101
    15. 001110010000000111011110000011000010101000111000000110101101
    16. 100100011101011111001101001010011111110010111101000010000111
    17. 110010100110101100001101111101010011000110101100000110001010
    18. 110101101100001110000100010001001010100010110100100001000011
    19. 100100000100001101010101001101000101101000000101111110001010
    20. 101101011010101000111110110000110100000010011111111100110010
    21. 101111000100000100011000010001011111001010010001010110001010
    22. 001010001110101010000100010011101001010101101101010111100101
    23. 001111110000101100010111111100000100101010000001011101100001
    24. 101011110010000010010110000100001010011111100011011000110010
    25. 011110010100011101100101111101000001011100001011010001110011
    26. 000101000101000010010010110111000010101111001101100110011100
    27. 100011100110011111000110011001111100001110110111001001000111
    28. 111011000110001000110111011001011110010010010110101000011111
    29. 011110011110110110011011001011010000100100101010110000010011
    30. 010011110011100101010101111010001001001111101111101110011101

    如果从一个标为 1 的位置可以通过上下左右走到另一个标为 1 的位置,则称两个位置连通。与某一个标为 1 的位置连通的所有位置(包括自己)组成一个连通分块。  

    请问矩阵中最大的连通分块有多大?

    思路:

    答案是148

    bfs进入为1的点,上下左右扩展计数,最后求每一次bfs最大值即可,模板提 

    1. import java.util.*;
    2. public class abc {
    3. static int n=30,m=60;
    4. static int[][] g=new int[n][m];
    5. static int[][] st=new int[n][m];
    6. static int[] dx={0,0,1,-1},dy= {1,-1,0,0};
    7. public static void main(String[] args)
    8. {
    9. Scanner sc=new Scanner(System.in);
    10. String t;
    11. for(int i=0;i
    12. {
    13. String s=sc.next();
    14. for(int j=0;j'0';
    15. }
    16. int res=0;
    17. for(int i=0;i
    18. {
    19. for(int j=0;j
    20. {
    21. if(g[i][j]==1&&st[i][j]==0)
    22. res=Math.max(res, bfs(i,j));
    23. }
    24. }
    25. System.out.print(res);
    26. }
    27. public static int bfs(int x,int y)
    28. {
    29. int cnt=1;
    30. st[x][y]=1;
    31. Queue q=new LinkedList<>();
    32. q.offer(new PII(x,y));
    33. while(!q.isEmpty())
    34. {
    35. PII t=q.poll();
    36. int xx=t.x,yy=t.y;
    37. for(int i=0;i<4;i++)
    38. {
    39. int nx=dx[i]+xx,ny=dy[i]+yy;
    40. if(nx>=0&&nx=0&&ny0&&g[nx][ny]==1)
    41. {
    42. st[nx][ny]=1;
    43. q.offer(new PII(nx,ny));
    44. cnt++;
    45. }
    46. }
    47. }
    48. return cnt;
    49. }
    50. }
    51. class PII
    52. {
    53. int x,y;
    54. PII(int x,int y)
    55. {
    56. this.x=x;
    57. this.y=y;
    58. }
    59. }

    F、哪一天?

    1<=n<=10^6

    思路:

    注意特判整除7的情况,不能输出0,应该输出7 

    1. import java.util.*;
    2. public class abc {
    3. public static void main(String[] args)
    4. {
    5. Scanner sc=new Scanner(System.in);
    6. int w=sc.nextInt(),n=sc.nextInt();
    7. int res=(w+n%7)%7;
    8. System.out.print(res==0? 7:res);
    9. }
    10. }

    G、信号覆盖 - bfs

    问题描述

            小蓝负责一块区域的信号塔安装,整块区域是一个长方形区域,建立坐标轴后,西南角坐标为 (0, 0), 东南角坐标为 (W, 0), 西北角坐标为 (0, H), 东北角坐标为 (W, H)。其中 W, H 都是整数。
            他在 n 个位置设置了信号塔,每个信号塔可以覆盖以自己为圆心,半径为 R 的圆形(包括边缘)。
            为了对信号覆盖的情况进行检查,小蓝打算在区域内的所有横纵坐标为整数的点进行测试,检查信号状态。其中横坐标范围为 0 到 W,纵坐标范围为 0 到 H,总共测试 (W+1) * (H+1) 个点。
            给定信号塔的位置,请问这 (W+1)*(H+1) 个点中有多少个点被信号覆盖。

    输入格式

            输入第一行包含四个整数 W, H, n, R,相邻整数之间使用一个空格分隔。
            接下来 n 行,每行包含两个整数 x, y,表示一个信号塔的坐标。信号塔可能重合,表示两个信号发射器装在了同一个位置。

    输出格式

            输出一行包含一个整数,表示答案。

    样例输入

    10 10 2 5
    0 0
    7 0

    样例输出

    57

    评测用例规模与约定

    1 <= W, H <= 100

    1 <= n <= 100

    1 <= R <= 100

    0 <= x <= W

    0 <= y <= H

    (1)bfs(60%)

    can you tell me why? 

    思路:

    st数组标记被覆盖的坐标点,对于每个信号塔进行bfs,对每个点上下左右扩展

    若【在合法范围内】且【未标记】且【该点到信号塔的距离<=r】,则入队标记 ,并统计覆盖点范围

    1. import java.util.*;
    2. public class abc {
    3. static int[][] st;
    4. static int res=0,r,h,w,n;
    5. static int[] dx={0,0,1,-1},dy= {1,-1,0,0};
    6. public static void main(String[] args)
    7. {
    8. Scanner sc=new Scanner(System.in);
    9. w=sc.nextInt();
    10. h=sc.nextInt();
    11. n=sc.nextInt();
    12. r=sc.nextInt();
    13. st=new int[w+1][h+1];
    14. for(int i=0;i
    15. {
    16. int x=sc.nextInt(),y=sc.nextInt();
    17. bfs(x,y);
    18. }
    19. for(int i=0;i<=w;i++)
    20. for(int j=0;j<=h;j++) if(st[i][j]==1) res++;
    21. System.out.print(res);
    22. }
    23. public static void bfs(int x,int y)
    24. {
    25. st[x][y]=1;
    26. Queue q=new LinkedList<>();
    27. q.offer(new PII(x,y));
    28. while(!q.isEmpty())
    29. {
    30. PII t=q.poll();
    31. int xx=t.x,yy=t.y;
    32. for(int i=0;i<4;i++)
    33. {
    34. int nx=dx[i]+xx,ny=dy[i]+yy;
    35. if(nx>=0&&nx<=w&&ny>=0&&ny<=h&&st[nx][ny]==0&&ck(x,y,nx,ny))
    36. {
    37. q.offer(new PII(nx,ny));
    38. st[nx][ny]=1;
    39. }
    40. }
    41. }
    42. }
    43. public static boolean ck(int x,int y,int nx,int ny)
    44. {
    45. int dis=(x-nx)*(x-nx)+(y-ny)*(y-ny);
    46. if(dis<=r*r) return true;
    47. return false;
    48. }
    49. }
    50. class PII
    51. {
    52. int x,y;
    53. PII(int x,int y)
    54. {
    55. this.x=x;
    56. this.y=y;
    57. }
    58. }

     (2)暴力

    1. import java.util.*;
    2. public class Main {
    3. public static void main(String[] args) {
    4. Scanner scan = new Scanner(System.in);
    5. int w = scan.nextInt(), h = scan.nextInt(), n = scan.nextInt(), r = scan.nextInt();
    6. int[][] arr = new int[n][2];
    7. for (int i = 0; i < n; i++) {
    8. arr[i][0] = scan.nextInt();
    9. arr[i][1] = scan.nextInt();
    10. }
    11. int count = 0;
    12. for (int i = 0; i <= w; i++) {
    13. for (int j = 0; j <= h; j++) {
    14. if (check(arr, n, r, i, j)) {
    15. count++;
    16. }
    17. }
    18. }
    19. System.out.println(count);
    20. }
    21. public static boolean check(int[][] arr, int n, int r, int x, int y) {
    22. for (int i = 0; i < n; i++) {
    23. int x0 = x - arr[i][0];
    24. int y0 = y - arr[i][1];
    25. if (x0 * x0 + y0 * y0 <= r * r) return true;
    26. }
    27. return false;
    28. }
    29. }

    H、清理水域 - 暴力(弱智版) 可以差分

    1. import java.util.*;
    2. public class abc {
    3. public static void main(String[] args)
    4. {
    5. Scanner sc=new Scanner(System.in);
    6. int n=sc.nextInt(),m=sc.nextInt(),t=sc.nextInt();
    7. int[][] g=new int[n+1][m+1];
    8. int res=0;
    9. while(t-->0)
    10. {
    11. int r1=sc.nextInt(),c1=sc.nextInt(),r2=sc.nextInt(),c2=sc.nextInt();
    12. for(int i=r1;i<=r2;i++)
    13. for(int j=c1;j<=c2;j++) g[i][j]=1;
    14. }
    15. for(int i=1;i<=n;i++)
    16. for(int j=1;j<=m;j++) if(g[i][j]==0) res++;
    17. System.out.print(res);
    18. }
    19. }

    I、滑行 - dfs + dp

    输入格式
      输入第一行包含两个整数 n, m,用一个空格分隔。
      接下来 n 行,每行包含 m 个整数,相邻整数之间用一个空格分隔,依次表示每个位置的高度。
    输出格式
      输出一行包含一个整数,表示答案。


    样例输入
    4 5
    1 4 6 3 1
    11 8 7 3 1
    9 4 5 2 1
    1 3 2 2 1
    样例输出
    7


    样例说明
      滑行的位置一次为 (2, 1), (2, 2), (2, 3), (3, 3), (3, 2), (4, 2), (4, 3)。

    评测用例规模与约定
      对于 30% 评测用例,1 <= n <= 20,1 <= m <= 20,0 <= 高度 <= 100。
      对于所有评测用例,1 <= n <= 100,1 <= m <= 100,0 <= 高度 <= 10000。

    (1)dfs(30%)

    1. import java.util.*;
    2. import java.math.*;
    3. public class Main {
    4. static int res=0;
    5. static int[] dx={0,0,1,-1},dy={1,-1,0,0};
    6. public static void main(String[] args) {
    7. Scanner sc = new Scanner(System.in);
    8. int n=sc.nextInt(),m=sc.nextInt();
    9. int[][] g=new int[n][m];
    10. for(int i=0;i
    11. for(int j=0;j
    12. for(int i=0;i
    13. for(int j=0;j
    14. {
    15. dfs(i,j,g,1,n,m);
    16. }
    17. System.out.print(res);
    18. sc.close();
    19. }
    20. public static int dfs(int x,int y,int[][] g,int cnt,int n,int m)
    21. {
    22. for(int i=0;i<4;i++)
    23. {
    24. int nx=x+dx[i],ny=y+dy[i];
    25. if(nx>=0&&nx=0&&ny
    26. {
    27. cnt++;
    28. res=Math.max(res,cnt);
    29. dfs(nx,ny,g,cnt,n,m);
    30. cnt--;
    31. }
    32. }
    33. return cnt;
    34. }
    35. }

    (2)dp+dfs(100%) 

    思路

    定义d[i][j]为从(i,j)出发能滑行的最长距离,则求出max每个d[i][j]即可

    1. import java.util.*;
    2. import java.math.*;
    3. public class Main {
    4. static int n,m,res=0;
    5. static int[][] g,d;
    6. static int[] dx={0,0,1,-1},dy={1,-1,0,0};
    7. public static void main(String[] args) {
    8. Scanner sc = new Scanner(System.in);
    9. n=sc.nextInt();
    10. m=sc.nextInt();
    11. g=new int[n][m];
    12. d=new int[n][m];
    13. for(int i=0;i
    14. for(int j=0;j
    15. for(int i=0;i
    16. for(int j=0;j
    17. res=Math.max(res,dfs(i,j));
    18. System.out.print(res);
    19. sc.close();
    20. }
    21. public static int dfs(int x,int y)
    22. {
    23. if(d[x][y]!=0) return d[x][y]; //如果这个点被访问过,返回从这个点能滑行的最大距离
    24. d[x][y]=1;
    25. for(int i=0;i<4;i++)
    26. {
    27. int nx=x+dx[i],ny=y+dy[i];
    28. if(nx>=0&&nx=0&&ny
    29. {
    30. d[x][y]=Math.max(d[x][y],dfs(nx,ny)+1);
    31. }
    32. }
    33. return d[x][y];
    34. }
    35. }

  • 相关阅读:
    数字IC秋招-基础/SOC/计算机体系结构
    模板学堂丨JumpServer安全运维审计大屏
    【计算机视觉】Graph Models算法介绍合集(四)
    Hive 基本操作
    C#完成XML文档节点的自动计算功能
    Odoo16—权限控制
    MVVM的构建(java&kotlin)
    看一遍学会Vue结合axios使用mockjs
    高并发缓存策略大揭秘:面试必备的缓存更新模式解析
    Cannot read properties of null (reading ‘insertBefore‘)
  • 原文地址:https://blog.csdn.net/weixin_61639349/article/details/134447019