大家好,我是snippet,今天是刷蓝桥真题的第五天,今天有动态规划的知识点,下面是我今天的题解
目录
一、数的分解
题目要求:
题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
把 2019 分解成 3 个各不相同的正整数之和,并且要求每个正整数都不包含数字 2 和 4,一共有多少种不同的分解方法?
注意交换 3 个整数的顺序被视为同一种方法,例如 1000+1001+18 和 1001+1000+18 被视为同一种。
运行限制
最大运行时间:1s
最大运行内存: 128M
解题思路:
直接两层for循环暴力枚举,再进行数位判断,如果满足条件直接ans++
代码:
package 蓝桥杯31天真题冲刺.Day5;
import java.io.*;
/**
* @author snippet
* @data 2023-03-07
* 数的分解-蓝桥云课
*/
public class T1_数的分解 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static StreamTokenizer st = new StreamTokenizer(br);
static int ans;
// 判断这个数是否包含2 和 4
static boolean check(int n) {
while (n != 0) {
if (n % 10 == 2 || n % 10 == 4) return false;
n /= 10;
}
return true;
}
public static void main(String[] args) throws IOException {
for (int i = 1; i <= 2019; i++) {
for (int j = i+1; j <= 2019; j++) {
int k = 2019-i-j;
if ((i < j) && (j < k)) {
if (check(i) && check(j) && check(k)) ans++;
}
}
}
pw.println(ans);
pw.flush();
br.close();
}
}
二、猜生日
题目要求:
题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
今年的植树节(2012 年 3 月 12 日),小明和他的叔叔还有小伙伴们一起去植树。休息的时候,小明的同学问他叔叔多大年纪,他叔叔说:“我说个题目,看你们谁先猜出来!”
“把我出生的年月日连起来拼成一个 8 位数(月、日不足两位前补 0)正好可以被今天的年、月、日整除!”
他想了想,又补充到:“再给个提示,我是 6 月出生的。”
根据这些信息,请你帮小明算一下,他叔叔的出生年月日。
格式是年月日连成的 8 位数。例如,如果是 1948 年 6 月 12 日,就写:19480612。
运行限制
最大运行时间:1s
最大运行内存: 128M
解题思路:
题目已经给了月份,我们只用遍历年份和日,然后用StringBuilder把年月日连起来,再用check函数判断数据是否符合条件就可以了
代码:
package 蓝桥杯31天真题冲刺.Day5;
import java.io.*;
/**
* @author snippet
* @data 2023-03-08
* 猜生日-蓝桥云课
*/
public class T2_猜生日 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static StreamTokenizer st = new StreamTokenizer(br);
static int ans = 0;
static boolean check(int x) {
if (x % 2012 == 0 && x % 3 == 0 && x % 12 == 0) return true;
return false;
}
public static void main(String[] args) throws IOException {
for (int i = 1900; i <= 2000; i++) {
for (int j = 1; j <= 30; j++) {
StringBuilder s = new StringBuilder("");
s.append(i);
s.append("06");
if (j <= 9) s.append("0" + j);
else s.append(j);
String str = s.toString();
if (check(Integer.parseInt(str))) {
pw.println(str);
}
}
}
pw.flush();
br.close();
}
}
三、成绩统计
题目要求:
题目描述
小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是一个 0 到 100 的整数。
如果得分至少是 60 分,则称为及格。如果得分至少为 85 分,则称为优秀。
请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整 数。
输入描述
输入的第一行包含一个整数 n (1≤n≤104),表示考试人数。
接下来 n 行,每行包含一个 0 至 100 的整数,表示一个学生的得分。
输出描述
输出两行,每行一个百分数,分别表示及格率和优秀率。百分号前的部分 四舍五入保留整数。
解题思路:
遍历所有分数,然后记录大于等于60分的人数和大于等于85分的人数,再与总人数相除然后向上取整即可
代码:
package 蓝桥杯31天真题冲刺.Day5;
import java.io.*;
/**
* @author snippet
* @data 2023-03-07
* 成绩统计-蓝桥云课
*/
public class T3_成绩统计 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static StreamTokenizer st = new StreamTokenizer(br);
static int n;// n表示学生个数
static double cnt1,cnt2;// cnt1存大于等于60分的学生人数 cnt2存大于等于85分的学生个数
public static void main(String[] args) throws IOException {
n = nextInt();
for (int i = 0; i < n; i++) {
int temp = nextInt();
if (temp >= 60) cnt1++;
if (temp >= 85) cnt2++;
}
pw.println(Math.round(cnt1/n * 100) + "%");
pw.println(Math.round(cnt2/n * 100) + "%");
pw.flush();
br.close();
}
static int nextInt() throws IOException {
st.nextToken();
return (int)st.nval;
}
}
四、最大和
题目要求:
问题描述
小蓝在玩一个寻宝游戏, 游戏在一条笔直的道路上进行, 道路被分成了 n 个方格, 依次编号 1 至 n, 每个方格上都有一个宝物, 宝物的分值是一个整数 (包括正数、负数和零), 当进入一个方格时即获得方格中宝物的分值。小蓝可 以获得的总分值是他从方格中获得的分值之和。
小蓝开始时站在方格 1 上并获得了方格 1 上宝物的分值, 他要经过若干步 到达方格 n。
当小蓝站在方格 p 上时, 他可以选择跳到 p+1 到 p+D(n−p) 这些方格中的一个, 其中 D(1)=1,D(x)(x>1) 定义为 x 的最小质因数。
给定每个方格中宝物的分值, 请问小蓝能获得的最大总分值是多少。
输入格式
输入的第一行包含一个正整数 n 。
第二行包含 n 个整数, 依次表示每个方格中宝物的分值。
输出格式
输出一行包含一个整数, 表示答案。
评测用例规模与约定
对于 40% 的评测用例, 1≤n≤100 。
对于 80% 的评测用例, 1≤n≤1000 。
对于所有评测用例, 1≤n≤10000, 每个宝物的分值为绝对值不超过 10^5 的整数。
运行限制
最大运行时间:1s
最大运行内存: 256M
解题思路:
这个题考的是动态规划和质数,因为我们要求从第一个方格到最后方格的最大总分值,又因为当小蓝站在方格 p 上时, 他可以选择跳到 p+1 到 p+D(n−p) 这些方格中的一个,所以我们需要先用筛求出每个数的最小质因数,然后对每个方格可达到的方格进行状态转移,注意:f 数组记得开long
代码:
package 蓝桥杯31天真题冲刺.Day5;
import java.io.*;
import java.util.Arrays;
/**
* @author snippet
* @data 2023-03-08
* 最大和-蓝桥云课
*/
// 动态规划
public class T4_最大和 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static StreamTokenizer st = new StreamTokenizer(br);
static int n;// n表示数据个数
static int[] arr;// 一维数组arr存原始数据
static int[] prime;// 一维数组prime存数字 i 的最小质因数
static long[] f;// 一维数组 f 存 1->i 距离的最大和值
// 求每个数的最小质因数
static void check() {
for (int i = 2; i < n; i++) {
for (int j = 2; j*j <= i; j++) {
if (i % j == 0) {
prime[i] = j;
break;
}
}
// 如果 prime[i] == 0表示这个数是质数
if (prime[i] == 0) prime[i] = i;
}
}
public static void main(String[] args) throws IOException {
n = nextInt();
arr = new int[n+1];
prime = new int[n+1];
f = new long[n + 1];
for (int i = 1; i <= n; i++) {
arr[i] = nextInt();
}
// 初始化
prime[1] = 1;
check();
// 初始化
Arrays.fill(f, -0x3f3f3f3f);
f[1] = arr[1];
for (int i = 1; i < n; i++) {
int t = prime[n-i];
for (int j = 1; j <= t; j++) {
int k = i + j;
// 状态转移
if (k <= n) f[k] = Math.max(f[k], f[i]+arr[k]);
}
}
pw.println(f[n]);
pw.flush();
br.close();
}
static int nextInt() throws IOException {
st.nextToken();
return (int)st.nval;
}
}