大家好,我是snippet,今天是刷蓝桥真题的第二十天了,已经过了三分之二的时间,在这过程中我也落下了一些“难题”,也有所收获,还有半个月就要省赛了,加油,冲击国赛,下面是我今天的题解
目录
一、纸张尺寸
题目内容:
问题描述
在 ISO 国际标准中定义了 A0 纸张的大小为 1189mm ×× 841mm, 将 A0 纸 沿长边对折后为 A1 纸, 大小为 841mm ×× 594mm, 在对折的过程中长度直接取 下整 (实际裁剪时可能有损耗)。将 A1 纸沿长边对折后为 A2 纸, 依此类推。
输入纸张的名称, 请输出纸张的大小。
输入格式
输入一行包含一个字符串表示纸张的名称, 该名称一定是 A0、A1、A2、 A3、A4、A5、A6、A7、A8、A9 之一。
输出格式
输出两行,每行包含一个整数,依次表示长边和短边的长度。
样例输入1
A0
样例输出1
1189
841样例输入 2
A1
样例输出 2
841
594运行限制
- 最大运行时间:1s
- 最大运行内存: 512M
解题思路:
暴力循环我们需要折纸的次数,然后将纸进行对折
代码:
package 蓝桥杯31天真题冲刺.Day20;
import java.util.Scanner;
/**
* @author snippet
* @data 2023-03-23
* 纸张尺寸-蓝桥云课
*/
public class T1_纸张尺寸 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int r = 1189;
int c = 841;
String s = sc.next();
int k = s.charAt(1) - '0';
while (k-- > 0) {
if (r > c) r /= 2;
else c /= 2;
}
System.out.println(Math.max(r, c));
System.out.println(Math.min(r, c));
}
}
二、最大数字
题目内容:
问题描述
给定一个正整数 N 。你可以对 N 的任意一位数字执行任意次以下 2 种操 作:
将该位数字加 1 。如果该位数字已经是 9 , 加 1 之后变成 0 。
将该位数字减 1 。如果该位数字已经是 0 , 减 1 之后变成 9 。
你现在总共可以执行 1 号操作不超过 A 次, 2 号操作不超过 B 次。 请问你最大可以将 N 变成多少?
输入格式
第一行包含 3 个整数: N,A,B 。
输出格式
一个整数代表答案。
样例输入
123 1 2
样例输出
933
样例说明
对百位数字执行 2 次 2 号操作, 对十位数字执行 1 次 1 号操作。
评测用例规模与约定
对于 30%30% 的数据, 1≤N≤100;0≤A,B≤10。
对于 100%100% 的数据, 1≤N≤1017;0≤A,B≤100
运行限制
- 最大运行时间:1s
- 最大运行内存: 512M
解题思路:
它是求修改之后最大的数,那我们就将给定的数的每个数位进行修改,并且递归每一种情况,就是操作一跟操作二的交互使用,使得到的数最大
代码:
package 蓝桥杯31天真题冲刺.Day20;
import java.util.Scanner;
/**
* @author snippet
* @data 2023-03-23
* 最大数字-蓝桥云课
*/
// dfs
public class T2_最大数字 {
static String s;
static int a,b;
static long ans = 0;
/**
* dfs搜索
* @param index 遍历数据到的数据的下标
* @param v 每次数位遍历完的数据的和值
*/
static void dfs(int index, long v) {
if (index < s.length()) {
// x表示每个位置数的大小
int x = s.charAt(index) - '0';
// 先进行操作一
int t = Math.min(a, 9 - x);
a -= t;
// 对下一位进行递归
dfs(index + 1, v * 10 + x + t);
// 回溯
a += t;
// 进行操作二
// 当该位为0时 进行操作则变为9 此时的值最大
// 那当操作二的操作此时大于该数位时 可以进行操作二x+1次
// 这个数位就变为9了 也就是最大了
if (b > x) {
b -= x + 1;
// 对下一位进行递归
dfs(index + 1, v * 10 + 9);
// 回溯
b += x + 1;
}
} else {
// 更新最大和值
ans = Math.max(ans, v);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
s = String.valueOf(sc.nextLong());
a = sc.nextInt();
b = sc.nextInt();
dfs(0, 0);
System.out.println(ans);
}
}
三、全排列的价值
题目链接:全排列的价值 - 蓝桥云课 (lanqiao.cn)
题目内容:
问题描述
对于一个排列 A=(a1,a2,⋯,an), 定义价值 ci 为 a1 至 ai−1 中小于 ai 的数 的个数, 即 ci=∣{aj∣j<i,aj<ai}∣。
定义 A 的价值为 ∑i=1nci 。
给定 n, 求 1 至 n 的全排列中所有排列的价值之和。
输入格式
输入一行包含一个整数 n 。
输出格式
输出一行包含一个整数表示答案, 由于所有排列的价值之和可能很大, 请 输出这个数除以 998244353 的余数。
样例输入 1
3
样例输出 1
9
样例输入 2
2022
样例输出 2
593300958
样例说明
1 至 3 构成的所有排列的价值如下:
(1,2,3):0+1+2=3
(1,3,2):0+1+1=2
(2,1,3):0+0+2=2
(2,3,1):0+1+0=1
(3,1,2):0+0+1=1
(3,2,1):0+0+0=0
故总和为 3+2+2+1+1=9 。
评测用例规模与约定
对于 40% 的评测用例, 0n≤20;
对于 70% 的评测用例, n≤5000;
对于所有评测用例, 2≤n≤10^6 。
运行限制
- 最大运行时间:1s
- 最大运行内存: 512M
解题思路:
对(n-1)个数插入n,它提供的价值分为两部分:
1.不改变之前的数的全排序的顺序,所以它提供的价值为 前面所有数的和*前面所有数的全排列的数量(高斯求和)
2.把n插入它的每个全排列中 插入之后变成了之前的4倍 f(n) = f(n−1)×n + i×(i−1) / 2 × g(n−1)
这个题可以参考执梗大佬的题解:第十三届蓝桥杯省赛Java A 组 F 题、Python A 组 G 题、Python B 组 G题——全排列的价值 (AC)_蓝桥杯全排列的价值_执 梗的博客-CSDN博客
代码:
package 蓝桥杯31天真题冲刺.Day20;
import java.io.*;
/**
* @author snippet
* @data 2023-03-23
* 全排列的价值-蓝桥云课
*/
// 动态规划
public class T3_全排列的价值 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static int n;
static int N = 1000100;
static int mod = 998244353;
static long[] f = new long[N];
static long[] g = new long[N];// 一维数组g存i!的值
public static void main(String[] args) throws IOException {
n = Integer.parseInt(br.readLine());
f[1] = 0;
long k = 1;
for (int i = 1; i <= n; i++) {
k *= i;
k %= mod;
g[i] = k;
}
// 对(n-1)个数插入n,它提供的价值分为两部分:
// 1.不改变之前的数的全排序的顺序,所以它提供的价值为 前面所有数的和*前面所有数的全排列的数量
// 2.把n插入它的每个全排列中 插入之后变成了之前的4倍
// f(n) = f(n−1)×n + i×(i−1) / 2 × g(n−1)
for (int i = 2; i <= n; i++) {
f[i] = (f[i-1]*i%mod + ((long)i*(i-1)/2)%mod * g[i-1]%mod)%mod;
}
pw.println(f[n]);
pw.flush();
br.close();
}
}