【2020年蓝桥杯Java-B组国赛题解】

2023-10-08 13:30

本文主要是介绍【2020年蓝桥杯Java-B组国赛题解】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2020年蓝桥杯Java-B组国赛

      • 🍡 A 美丽的2(模拟)
      • 🍯 B 扩散(BFS多起点搜索)
      • 🍕 C 阶乘约数(不同约数个数问题)
      • ※🥙 D 本质上升序列(DP)
      • 🥘 E 玩具蛇(DFS多起点)
      • 🥞 F 蓝肽子序列(DP:最长公共子序列)
      • 🍶 G 皮亚诺曲线

🍡 A 美丽的2(模拟)

【问题描述】
小蓝特别喜欢 2,今年是公元 2020 年,他特别高兴。他很好奇,在公元 1 年到公元 2020 年(包含)中,有多少个年份的数位中包含数字 2?

答案:563

🍯 B 扩散(BFS多起点搜索)

【问题描述】
小蓝在一张无限大的特殊画布上作画。
这张画布可以看成一个方格图,每个格子可以用一个二维的整数坐标表示。

小蓝在画布上首先点了一下几个点:(0, 0), (2020, 11), (11, 14), (2000, 2000)。只有这几个格子上有黑色,其它位置都是白色的。
每过一分钟,黑色就会扩散一点。具体的,如果一个格子里面是黑色,它就会扩散到上、下、左、右四个相邻的格子中,使得这四个格子也变成黑色(如果原来就是黑色,则还是黑色)。

请问,经过 2020 分钟后,画布上有多少个格子是黑色的。

典型的BFS,属于是多起点的BFS题目。注意原来是黑点的就不用再入队,否则会运行超时。

import java.util.*;
import java.io.*;class node {int x, y;node() {}node(int x, int y) {this.x = x;this.y = y;}
}
public class Main {static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));static int[] xx = new int[] {0,0,1,-1};static int[] yy = new int[] {1,-1,0,0};public static void main(String[] args) throws IOException {// 为避免出现负数情况,所有值都+2020int x1 = 2020;int y1 = 2020;int x2 = 4040;int y2 = 2020 + 11;int x3 = 2020 + 11;int y3 = 2020 + 14;int x4 = 2020 + 2000;int y4 = 2020 + 2000;int[][] point = new int[7000][7000];Queue<node> queue = new LinkedList<>();queue.offer(new node(x1, y1));queue.offer(new node(x2, y2));queue.offer(new node(x3, y3));queue.offer(new node(x4, y4));// 记录轮数int time = 0;while (!queue.isEmpty()) {int size = queue.size();for (int i = 0; i < size; i++) {node cur = queue.poll();for (int j = 0; j < 4; j++) {int tx = cur.x + xx[j];int ty = cur.y + yy[j];// 注意不要重复入队,否则必超时if (point[tx][ty] == 1) continue;point[tx][ty] = 1;queue.offer(new node(tx, ty));}}// 全部完成一轮time++;if (time == 2020) {break;}}int ans = 0;for (int i = 0; i < 7000; i++) {for (int j = 0; j < 7000; j++) {if (point[i][j] == 1) {ans++;}}}System.out.println(ans);}
}

答案:20312088

🍕 C 阶乘约数(不同约数个数问题)

在这里插入图片描述

在这里插入图片描述
对于数字4,可以拆分成2的2次方,所以4的全部因数(约数)个数 = 1 * 3 = 3(1 2 4三个),这里要注意区别质因数、因数(约数),我们是用到了:一个自然数可以唯一地表示成一些质因数的乘积,这个定理,在此基础上引出了求解自然数N的全部因数(约数)个数的方法。

回到本题,要求100阶乘的正约数,也就是求1-100每个数的正约数个数即可。
上面的定理一定要记牢,遇到求约数问题常常会考!!!

答案:39001250856960000

import java.util.*;
import java.io.*;public class Main {static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));public static void main(String[] args) throws IOException {// 记录所有质因数的次数int[] cnt = new int[110];for (int i = 1; i <= 100; i++) {int tmp = i;for (int j = 2; j <= Math.sqrt(tmp); j++) {// 求所有可能质因数while (tmp % j == 0) {cnt[j]++;tmp /= j;}}// 说明i是质数if (tmp != 1) {cnt[tmp]++;}}// 统计所有正约数个数long ans = 1L;for (int i = 1; i <= 100; i++) {ans *= (1 + cnt[i]);}System.out.println(ans);}
}

※🥙 D 本质上升序列(DP)

在这里插入图片描述

tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhf
iadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqij
gihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmad
vrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl

答案:3616159

有点类似于<最长递增子序列>,但又不是求最大长度,而是求种类数,那么肯定需要对dp数组的值进行累加。

dp[i],表示以字符串中第 i 个元素结尾的子串的本质不同的递增子序列的个数,而每一个子串,无非就是以每个元素结尾的,所以最终我们要求的结果就 = dp[0] + dp[1] + dp[2] + … + dp[n - 1]。

显然,对于单独每个字符,个数都=1。
对于abcd而言,站在c的角度往前考虑,c的前面可以放a、b,c可以直接放在a后面,也可以直接放在b后面(b前面放什么就由b自己来管,c不用管),所以dp[c] += dp[a] dp[c] += dp[b]。这是前面的字符小于后面字符的情况,如果等于呢?

对于abcbd而言,站在第二个b的角度向前考虑,考虑到前面第一个b时,发现 b == b,因为题目要求严格递增,并且要本质不同,所以需要将dp[b2] -= dp[b1],因为dp[b2]会统计第一个b之前的组合方式,但b1之前已经统计过了,b2再统计就重复了,所以需要减去。
d p [ i ] + = d p [ j ] i f s t r [ j ] < s t r [ i ] d p [ i ] − = d p [ j ] i f s t r [ j ] = s t r [ i ] 0 < j < i < l e n g t h dp[i] += dp[j] \quad if str[j] < str[i] \\ dp[i] -= dp[j] \quad if str[j] =str[i] \\ 0 < j < i < length dp[i]+=dp[j]ifstr[j]<str[i]dp[i]=dp[j]ifstr[j]=str[i]0<j<i<length

import java.util.*;
import java.io.*;public class Main {static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));public static void main(String[] args) throws IOException {String str = "tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl";char[] chars = str.toCharArray();int n = chars.length;// dp[i] 前i个字符的本质不同的递增子序列有多少个int[] dp = new int[n + 1];// 对于每个单独的字符,值都=1Arrays.fill(dp, 1);for (int i = 0; i < n; i++) {for (int j = 0; j < i; j++) {if (chars[j] < chars[i]) {dp[i] += dp[j];}if (chars[j] == chars[i]) {dp[i] -= dp[j];}}}long ans = 0L;for (int i = 0; i < n; i++) {ans += dp[i];}System.out.println(ans);}
}

🥘 E 玩具蛇(DFS多起点)

小蓝有一条玩具蛇,一共有 16 节,上面标着数字 1 至 16。每一节都是一个正方形的形状。相邻的两节可以成直线或者成 90 度角。小蓝还有一个 4 × 4 的方格盒子,用于存放玩具蛇,盒子的方格上依次标着字母 A 到 P 共 16 个字母。

小蓝可以折叠自己的玩具蛇放到盒子里面。他发现,有很多种方案可以将玩具蛇放进去。

在这里插入图片描述
DFS搜索,每个点都可以作为起点,注意搜索之后要回溯。
答案:552

import java.util.*;
import java.io.*;public class Main {static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));static boolean[][] vis = new boolean[5][5];static int[] x = new int[] {0,0,1,-1};static int[] y = new int[] {1,-1,0,0};static int ans = 0;public static void main(String[] args) throws IOException {// 枚举所有可能起点for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {// 每次从新起点开始遍历都需要重置visvis = new boolean[5][5];vis[i][j] = true;dfs(i, j, 2);}}System.out.println(ans);}static void dfs(int xx, int yy, int next) {if (next == 16 + 1) {ans++;return;}for (int i = 0; i < 4; i++) {int tx = xx + x[i];int ty = yy + y[i];if (tx < 0 || ty < 0 || tx >= 4 || ty >= 4) continue;if (vis[tx][ty]) continue;// 当前位置可以放vis[tx][ty] = true;dfs(tx, ty, next + 1);// 回溯,不放当前位置,注意:固定了起点vis[tx][ty] = false;}}
}

🥞 F 蓝肽子序列(DP:最长公共子序列)

在这里插入图片描述
在这里插入图片描述
看这道题之前,先看看这道<最长公共子序列>问题:
在这里插入图片描述
此题属于编辑距离类题目的典型问题,动态转移方程都类似,不了解的同学可以去这里看看,动态规划专题一

定义dp[i][j]数组含义为:text1[1…i] 与 text2[1…j] 的最长公共子序列的最大长度,所以最终答案 = dp[n1][n2]。

class Solution {public int longestCommonSubsequence(String text1, String text2) {int n1 = text1.length();int n2 = text2.length();// dp[i][j] // text1[1...i] 与 text2[1...j] 的最长公共子序列的长度int[][] dp = new int[n1 + 1][n2 + 1];for (int i = 1; i <= n1; i++) {for (int j = 1; j <= n2; j++) {// 两个字符相等if (text1.charAt(i - 1) == text2.charAt(j - 1)) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {// 如果不相等,取决于删除text1 或 text2中某个字符的最大情况dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);}}}return dp[n1][n2];}
}

回到本题,看了上面的代码后,相信大家都有思路了,不就是把dp考虑的最小单位从字符变到了字符串。

import java.util.*;
import java.io.*;public class Main {static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));public static void main(String[] args) throws IOException {String a = reader.readLine().trim();String b = reader.readLine().trim();// 提取出每个蓝肽序列中的子序列String[] str_a = new String[1000];String[] str_b = new String[1000];int n1 = a.length();int n2 = b.length();// 找第一个蓝肽序列的子序列int index = 0;for (int i = 0;;) {if (i >= n1) break;char c = a.charAt(i);// 找到了蓝肽的大写字母开头if (c >= 'A' && c <= 'Z') {int j = i + 1;// 找到当前蓝肽的结束位置while (j < n1 && a.charAt(j) >= 'a' && a.charAt(j) <= 'z') {j++;}String sub = a.substring(i, j);str_a[index++] = sub;i += sub.length();}}n1 = index;// 找第二个蓝肽序列的子序列index = 0;for (int i = 0;;) {if (i >= n2) break;char c = b.charAt(i);// 找到了蓝肽的大写字母开头if (c >= 'A' && c <= 'Z') {int j = i + 1;// 找到当前蓝肽的结束位置while (j < n2 && b.charAt(j) >= 'a' && b.charAt(j) <= 'z') {j++;}String sub = b.substring(i, j);str_b[index++] = sub;i += sub.length();}}n2 = index;// dp[i][j], str_a[1...i] 与 str_b[1...j] 的最长公共子序列的长度// 这里考虑的基本单位为:子串,不再是之前题目中的字符int[][] dp = new int[n1 + 1][n2 + 1];for (int i = 1; i <= n1; i++) {for (int j = 1; j <= n2; j++) {// 对应于两个字符相等的情况if (str_a[i - 1].equals(str_b[j - 1])) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {// 如果不等,取决于两个中的最大值dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);}}}System.out.println(dp[n1][n2]);}
}

喜欢这种自己摸得着的题目,哈哈哈哈哈,好歹知道该怎么进行转换。

🍶 G 皮亚诺曲线

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
没想到好的解决方案。

这篇关于【2020年蓝桥杯Java-B组国赛题解】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/165626

相关文章

Spring Boot项目部署命令java -jar的各种参数及作用详解

《SpringBoot项目部署命令java-jar的各种参数及作用详解》:本文主要介绍SpringBoot项目部署命令java-jar的各种参数及作用的相关资料,包括设置内存大小、垃圾回收... 目录前言一、基础命令结构二、常见的 Java 命令参数1. 设置内存大小2. 配置垃圾回收器3. 配置线程栈大小

SpringBoot实现微信小程序支付功能

《SpringBoot实现微信小程序支付功能》小程序支付功能已成为众多应用的核心需求之一,本文主要介绍了SpringBoot实现微信小程序支付功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作... 目录一、引言二、准备工作(一)微信支付商户平台配置(二)Spring Boot项目搭建(三)配置文件

解决SpringBoot启动报错:Failed to load property source from location 'classpath:/application.yml'

《解决SpringBoot启动报错:Failedtoloadpropertysourcefromlocationclasspath:/application.yml问题》这篇文章主要介绍... 目录在启动SpringBoot项目时报如下错误原因可能是1.yml中语法错误2.yml文件格式是GBK总结在启动S

Spring中配置ContextLoaderListener方式

《Spring中配置ContextLoaderListener方式》:本文主要介绍Spring中配置ContextLoaderListener方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录Spring中配置ContextLoaderLishttp://www.chinasem.cntene

java实现延迟/超时/定时问题

《java实现延迟/超时/定时问题》:本文主要介绍java实现延迟/超时/定时问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java实现延迟/超时/定时java 每间隔5秒执行一次,一共执行5次然后结束scheduleAtFixedRate 和 schedu

Java Optional避免空指针异常的实现

《JavaOptional避免空指针异常的实现》空指针异常一直是困扰开发者的常见问题之一,本文主要介绍了JavaOptional避免空指针异常的实现,帮助开发者编写更健壮、可读性更高的代码,减少因... 目录一、Optional 概述二、Optional 的创建三、Optional 的常用方法四、Optio

Spring Boot项目中结合MyBatis实现MySQL的自动主从切换功能

《SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能》:本文主要介绍SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能,本文分步骤给大家介绍的... 目录原理解析1. mysql主从复制(Master-Slave Replication)2. 读写分离3.

idea maven编译报错Java heap space的解决方法

《ideamaven编译报错Javaheapspace的解决方法》这篇文章主要为大家详细介绍了ideamaven编译报错Javaheapspace的相关解决方法,文中的示例代码讲解详细,感兴趣的... 目录1.增加 Maven 编译的堆内存2. 增加 IntelliJ IDEA 的堆内存3. 优化 Mave

Java String字符串的常用使用方法

《JavaString字符串的常用使用方法》String是JDK提供的一个类,是引用类型,并不是基本的数据类型,String用于字符串操作,在之前学习c语言的时候,对于一些字符串,会初始化字符数组表... 目录一、什么是String二、如何定义一个String1. 用双引号定义2. 通过构造函数定义三、St

springboot filter实现请求响应全链路拦截

《springbootfilter实现请求响应全链路拦截》这篇文章主要为大家详细介绍了SpringBoot如何结合Filter同时拦截请求和响应,从而实现​​日志采集自动化,感兴趣的小伙伴可以跟随小... 目录一、为什么你需要这个过滤器?​​​二、核心实现:一个Filter搞定双向数据流​​​​三、完整代码