【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

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c