蓝桥杯 2022年国赛真题
Java 大学A组
先做做 CB。
试题 A: 火柴棒数字
本题总分: 5 5 5 分
【问题描述】
小蓝最近迷上了用火柴棒拼数字字符,方法如下图所示 : : :
他只能拼 0 0 0 至 9 9 9 这十种数字字符,其中每个数字字符需要的火柴棒的数目依次是 : : : 6 , 2 , 5 , 5 , 4 , 5 , 6 , 3 , 7 , 6 6,2,5,5,4,5,6,3,7,6 6,2,5,5,4,5,6,3,7,6。他不喜欢重复拼同一个数字字符,所以对于每个数字字符他最多拼十个。小蓝会把拼出来的数字字符组合在一起形成一个整数, 例如对于整数 345 345 345,需要的火柴棒的数目为 5 + 4 + 5 = 14 5 + 4 + 5 = 14 5+4+5=14 根。小蓝有 300 300 300 根火柴棒,他想知道自己能拼出的最大整数是多少?可以不使用完这 300 300 300 根火柴棒,可以有多余的火柴棒剩下。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个由大写字母组成的字符串,在提交答案时只填写这个字符串,填写多余的内容将无法得分。
9999999999777777777755555555554444444444333333333322222222221111111111
多重背包
将数字视作价值为 1 1 1 且各有 10 10 10 个的物品,需要的火柴棒视作其重量,这显然是个多重背包问题。
不采用滚动数组以便还原组合方案,在还原方案的时候优先输出尽可能多的,值较大的数字即可。
public class Test {
public static void main(String[] args) {
new Test().run(); }
int N = 300, W[] = {
0,6,2,5,5,4,5,6,3,7,6 };
void run() {
int[][] dp = new int[11][N + 1];
for (int i = 1; i <= 10; ++i)
for (int k = 0; k <= 10; ++k)
for (int j = k * W[i]; j <= 300; ++j)
dp[i][j] = max(dp[i][j], dp[i - 1][j - k * W[i]] + k);
for (int i = 10, j = 300, k = 0; i > 0; --i, k = 0) {
for (int g = 1; g <= 10 && j - g * W[i] >= 0; ++g)
if (dp[i][j] <= dp[i - 1][j - g * W[i]] + g) k = g;
for (j -= k * W[i]; k > 0; --k) System.out.print(i - 1);
}
}
int max(int arg1, int arg2) {
return arg1 > arg2 ? arg1 : arg2; }
}
试题 B: 小蓝与钥匙
本题总分: 5 5 5 分
【问题描述】
小蓝是幼儿园的老师,他的班上有 28 28 28 个孩子,今天他和孩子们一起进行了一个游戏。
小蓝所在的学校是寄宿制学校, 28 28 28 个孩子分别有一个自己的房间,每个房间对应一把钥匙,每把钥匙只能打开自己的门。现在小蓝让这 28 28 28 个孩子分别将自己宿舍的钥匙上交,再把这 28 28 28 把钥匙随机打乱分给每个孩子一把钥匙,有 28 ! = 28 × 27 × ⋯ × 1 28! = 28×27×\cdots×1 28!=28×27×⋯×1 种分配方案。小蓝想知道这些方案中,有多少种方案恰有一半的孩子被分到自己房间的钥匙(即有 14 14 14 个孩子分到的是自己房间的钥匙,有 14 14 14 个孩子分到的不是自己房间的钥匙)。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
1286583532342313400
组合数学
28 28 28 个孩子中,任选 14 14 14 个孩子拿到自己房间钥匙的组合数乘以第 14 14 14 个错位排列数,即 C 28 14 × D 14 C_{28}^{14} \times D_{14} C2814×D14 就是我们所要提交的答案。
public class Test {
public static void main(String[] args) {
new Test().run(); }
void run() {
System.out.println(C(28, 14) * D(14)); }
long C(int n, int m) {
if (m > n || n < 0) return 0;
if (n == m) return 1;
return C(n - 1, m) + C(n - 1, m - 1);
}
long D(int n) {
if (n == 1) return 0;
if (n == 2) return 1;
return (n - 1) * (D(n - 1) + D(n - 2));
}
}
试题 C: 内存空间
时间限制: 3.0 s 3.0\mathrm s 3.0s 内存限制: 512.0 M B 512.0\mathrm{MB} 512.0MB 本题总分: 10 10 10 分
【问题描述】
小蓝最近总喜欢计算自己的代码中定义的变量占用了多少内存空间。
为了简化问题,变量的类型只有以下三种:
i n t : \mathrm{int}: int:整型变量,一个 i n t \mathrm{int} int 型变量占用 4 B y t e 4\ \mathrm{Byte} 4 Byte 的内存空间。
l o n g : \mathrm{long}: long:长整型变量,一个 l o n g \mathrm{long} long 型变量占用 8 B y t e 8\ \mathrm{Byte} 8 Byte 的内存空间。
S t r i n g : \mathrm{String}: String:字符串变量,占用空间和字符串长度有关,设字符串长度为 L L L,则字符串占用 L B y t e L\ \mathrm{Byte} L Byte 的内存空间,如果字符串长度为 0 0 0 则占用 0 B y t e 0\ \mathrm{Byte} 0 Byte 的内存空间。
定义变量的语句只有两种形式,第一种形式为 : : :
t y p e v a r 1 = v a l u e 1 , v a r 2 = v a l u e 2 ⋯ ; \mathrm{type\ var1=value1},\ \mathrm{var2=value2}\cdots; type var1=value1, var2=value2⋯;
定义了若干个 t y p e \mathrm{type} type 类型变量 v a r 1 \mathrm{var1} var1、 v a r 2 \mathrm{var2} var2、 ⋯ \cdots ⋯,并且用 v a l u e 1 \mathrm{value1} value1、 v a l u e 2 ⋯ \mathrm{value2}\cdots value2⋯ 初始化,
多个变量之间用 ’ , ’ ’,’ ’,’ 分隔,语句以 ’ ; ’ ’;’ ’;’ 结尾, t y p e \rm type type 可能是 i n t \rm int int、 l o n g \rm long long 或 S t r i n g \rm String String。例如 i n t a = 1 , b = 5 , c = 6 ; \rm int a=1,\ b=5,\ c=6; inta=1, b=5, c=6; 占用空间为 12 B y t e 12\ \rm Byte 12 Byte; l o n g a = 1 , b = 5 ; \rm long\ a=1,\ b=5; long a=1, b=5; 占用空间为 16 B y t e 16\ \rm Byte 16 Byte; S t r i n g s 1 = ”” , s 2 = ” h e l l o ” , s 3 = ” w o r l d ” ; \rm String \ s1=””,\ s2=”hello”,\ s3=”world”; String s1=””, s2=”hello”, s3=”world”; 占用空间为 10 B y t e 10\ \rm Byte 10 Byte。
第二种形式为 : : :
t y p e [ ] a r r 1 = n e w t y p e [ s i z e 1 ] , a r r 2 = n e w t y p e [ s i z e 2 ] ⋯ ; \rm type[\:]\ arr1=new\ type[size1],arr2=new\ type[size2]\cdots; type[] arr1=new type[size1],arr2=new type[size2]⋯;
定义了若干 t y p e \rm type type 类型的一维数组变量 a r r 1 \rm arr1 arr1、 a r r 2 ⋯ \rm arr2\cdots arr2⋯,且数组的大小为 s i z e 1 \rm size1 size1、 s i z e 2 ⋯ \rm size2\cdots size2⋯,多个变量之间用 ’ , ’ ’,’ ’,’ 进行分隔,语句以 ’ ; ’ ’;’ ’;’ 结尾, t y p e \rm type type 只可能是 i n t \rm int int 或 l o n g \rm long long。例如 i n t [ ] a 1 = n e w i n t [ 10 ] ; \rm int[\:]\ a1=new\ int[10]; int[] a1=new int[10]; 占用的内存空间为 40 B y t e 40\ \rm Byte 40 Byte; l o n g [ ] a 1 = n e w l o n g [ 10 ] , a 2 = n e w l o n g [ 10 ] ; \rm long[\:]\ a1=new\ long[10],\ a2=new\ long[10]; long[] a1=new long[10], a2=new long[10]; 占用的内存空间为 160 B y t e 160\ \rm Byte 160 Byte。
已知小蓝有 T T T 条定义变量的语句,请你帮他统计下一共占用了多少内存空间。结果的表示方式为 : : : a G B b M B c K B d B a\mathrm{GB}b\mathrm{MB}c\mathrm{KB}d\mathrm B aGBbMBcKBdB,其中 a a a、 b b b、 c c c、 d d d 为统计的结果, G B \rm GB GB、 M B \rm MB MB、 K B \rm KB KB、 B \rm B B 为单位。优先用大的单位来表示, 1 G B = 1024 M B \rm 1GB=1024MB 1GB=1024MB, 1 M B = 1024 K B \rm 1MB=1024KB 1MB=1024KB, 1 K B = 1024 B \rm 1KB=1024B 1KB=1024B,其中 B B B 表示 B y t e \rm Byte Byte。如果 a a a、 b b b、 c c c、 d d d 中的某几个数字为 0 0 0,那么不必输出这几个数字及其单位。题目保证一行中只有一句定义变量的语句,且每条语句都满足题干中描述的定义格式,所有的变量名都是合法的且均不重复。题目中的数据很规整,和上述给出的例子类似,除了类型后面有一个空格,以及定义数组时 n e w \rm new new 后面的一个空格之外,不会出现多余的空格。
【输入格式】
输入的第一行包含一个整数 T T T ,表示有 T T T 句变量定义的语句。
接下来 T T T 行,每行包含一句变量定义语句。
【输出格式】
输出一行包含一个字符串,表示所有语句所占用空间的总大小。
【样例输入 1】
1
long[] nums=new long[131072];
【样例输出 1】
1MB
【样例输入 2】
4
int a=0,b=0;
long x=0,y=0;
String s1="hello",s2="world";
long[] arr1=new long[100000],arr2=new long[100000];
【样例输出 2】
1MB538KB546B
【样例说明】
样例 1 1 1,占用的空间为 131072 × 8 = 1048576 B 131072×8 = 1048576\ \mathrm B 131072×8=1048576 B,换算过后正好是 1 M B 1\ \rm MB 1 MB,其 它三个单位 G B \rm GB GB、 K B \rm KB KB、 B \rm B B 前面的数字都为 0 0 0 ,所以不用输出。
样例 2 2 2,占用的空间为 4 × 2 + 8 × 2 + 10 + 8 × 100000 × 2 B 4×2 + 8×2 + 10 + 8×100000×2 \mathrm\ B 4×2+8×2+10+8×100000×2 B,换算后是 1 M B 538 K B 546 B 1\mathrm{MB}538\mathrm{KB}546\mathrm B 1MB538KB546B。
【评测用例规模与约定】
对于所有评测用例, 1 ≤ T ≤ 10 1 ≤ T ≤ 10 1≤T≤10,每条变量定义语句的长度不会超过 1000 1000 1000。所有的变量名称长度不会超过 10 10 10,且都由小写字母和数字组成。对于整型变 量,初始化的值均是在其表示范围内的十进制整数,初始化的值不会是变量。 对于 S t r i n g \rm String String 类型的变量,初始化的内容长度不会超过 50 50 50,且内容仅包含小写字母和数字,初始化的值不会是变量。对于数组类型变量,数组的长度为一个 整数,范围为 : : : [ 0 , 2 30 ] [0,2^{30}] [0,230],数组的长度不会是变量。 T T T 条语句定义的变量所占的内存空间总大小不会超过 1 G B 1\ \rm GB 1 GB,且大于 0 B 0\ \rm B 0 B。
挨喷题。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
new Main().run(); }
String[] unit = {
"", "K", "M", "G" };
void run() {
long count = 0;
try (BufferedReader in = new BufferedReader(new InputStreamReader(System.in))) {
for (int T = Integer.parseInt(in.readLine()); T-- > 0;) {
String line = in.readLine();
if (line.startsWith("String")) {
for (int flag = 0, i = 0, j = 0; i < line.length(); ++i) {
if (line.charAt(i) == '"') {
count += flag * (i - j - 1);
flag ^= 1;
j = i;
}
}
} else {
long buffer = 0;
if (line.charAt(3) == '[' || line.charAt(4) == '[')
for (int i = 6, j = 0; i < line.length(); ++i) {
if (line.charAt(i) == '[') j = i;
else if (line.charAt(i) == ']')
buffer += Integer.parseInt(line.substring(j + 1, i));
}
else buffer = line.split(",").length;
count += buffer << (line.startsWith("int") ? 2 : 3);
}
}
} catch (IOException e) {
e.printStackTrace();
}
for (int i = 3; i >= 0; --i)
if (count >> (i * 10) > 0) {
System.out.print((count >> (i * 10)) + unit[i] + 'B');
count &= (1 << (i * 10)) - 1;
}
}
}
试题 D: 斐波那契数组
时间限制: 3.0 s 3.0\mathrm s 3.0s 内存限制: 512.0 M B 512.0\mathrm{MB} 512.0MB 本题总分: 10 10 10 分
【问题描述】
如果数组 A = ( a 0 , a 1 , ⋯ , a n − 1 ) A = (a_0,a_1,\cdots ,a_{n−1}) A=(a0,a1,⋯,an−1) 满足以下条件,就说它是一个斐波那契数组 : : :
1. 1. 1. n ≥ 2 n≥2 n≥2;
2. 2. 2. a 0 = a 1 a_0 = a_1 a0=a1;
3. 3. 3. 对于所有的 i ( i ≥ 2 ) i(i≥2) i(i≥2),都满足 a i = a i − 1 + a i − 2 a_i = a_{i−1} + a_{i−2} ai=ai−1+ai−2。
现在,给出一个数组 A A A ,你可以执行任意次修改,每次修改将数组中的某个位置的元素修改为一个大于 0 0 0 的整数。请问最少修改几个元素之后,数组 A A A 会变成一个斐波那契数组。
【输入格式】
输入的第一行包含一个整数 n n n,表示数组 A A A 中的元素个数。
第二行包含 n n n 个整数 a 0 , a 1 , ⋯ , a n − 1 a_0,a_1, \cdot