2022 年 9 月青少年软编等考 C 语言二级真题解析
目录
- T1. 统计误差范围内的数
- 思路分析
- T2. 全在其中
- 思路分析
- T3. Lab 杯
- 思路分析
- T4. 有趣的跳跃
- 思路分析
- T5. 反反复复
- 思路分析
T1. 统计误差范围内的数
统计一个整数序列中与指定数字 m m m 误差范围小于等于 x x x 的数的个数。
时间限制:1 s
内存限制:64 MB
- 输入
输入包含三行:
第一行为 n n n,表示整数序列的长度, n ≤ 100 n \le 100 n≤100;
第二行为 n n n 个整数,整数之间以一个空格分开;
第三行包含 2 2 2 个整数,为指定的整数 m m m,误差范围 x x x。 - 输出
输出为 n n n 个数中与指定数字 m m m 误差范围小于等于 x x x 的数的个数。 - 样例输入
5 1 2 3 4 5 3 1
- 样例输出
3
- 提示
样例中 2 2 2, 3 3 3, 4 4 4 都满足条件,故答案为 3 3 3。
思路分析
此题考查一维数组的查找与统计,属于入门题。
此题与 2021 年 12 月二级 T1 类似,将给定数据存储在数组中之后,依次遍历每一个元素,检测其是否介于 m − x ∼ m + x m-x \sim m+x m−x∼m+x 范围内,若是,则计数器变量累加 1 1 1,最后输出计数器变量的值即可。
/*
* Name: T1.cpp
* Problem: 统计误差范围内的数
* Author: Teacher Gao.
* Date&Time: 2024/11/15 21:40
*/
#include <iostream>
using namespace std;
int main()
{
int n, a[105], m, x;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
cin >> m >> x;
int tot = 0;
for (int i = 1; i <= n; i++) {
if (m - x <= a[i] && a[i] <= m + x) {
tot++;
}
}
cout << tot;
return 0;
}
T2. 全在其中
你设计了一个新的加密技术,可以用一种聪明的方式在一个字符串的字符间插入随机的字符串从而对信息进行编码。由于专利问题,我们将不会详细讨论如何在原有信息中产生和插入字符串。不过,为了验证你的方法,有必要写一个程序来验证原来的信息是否全在最后的字符串之中。
给定两个字符串 s s s 和 t t t,你需要判断 s s s 是否是 t t t 的 “子列”。也就是说,如果你去掉 t t t 中的某些字符,剩下字符将连接而成为 s s s。
时间限制:1 s
内存限制:64 MB
- 输入
输入包括多个测试样例。每一个都是由空格分隔的由字母数字 ASCII \text{ASCII} ASCII 字符组成的两个特定的字符串 s s s 和 t t t。 s s s 和 t t t 的长度不超过 100000 100000 100000。 - 输出
对于每个测试样例,如果 s s s 是 t t t 的 “子列”,则输出Yes
,否则输出No
。 - 样例输入
sequence subsequence person compression VERDI vivaVittorioEmanueleReDiItalia caseDoesMatter CaseDoesMatter
- 样例输出
Yes No Yes No
思路分析
此题考查字符串遍历与查找,属于入门题。
我们可以依次遍历字符串
s
s
s 中的每一个字符
s
i
s_i
si,在
t
t
t 中查找
s
i
s_i
si 是否存在。这里需要设置一个变量
p
p
p 表示每一个
s
i
s_i
si 开始查找的位置,初始值为
0
0
0,再设置一个标记变量
f
l
a
g
flag
flag 表示是否查找成功,初始值为
t
r
u
e
true
true。若在
t
t
t 中查找到
s
i
s_i
si,则更新下一个字符开始查找的位置,若未找到,则将
f
l
a
g
flag
flag 置为
f
a
l
s
e
false
false 并结束查找。之后根据
f
l
a
g
flag
flag 变量的值输出 Yes
或 No
。
至于不定项输入,使用 while (cin >> ...)
即可。
/*
* Name: T2.cpp
* Problem: 全在其中
* Author: Teacher Gao.
* Date&Time: 2024/11/15 21:46
*/
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s, t;
while (cin >> s >> t) {
int len = s.length(), p = 0;
bool flag = true;
for (int i = 0; i < len; i++) {
int tmp = t.find(s[i], p);
if (tmp == -1) {
flag = false;
break;
}
p = tmp + 1;
}
if (flag) cout << "Yes\n";
else cout << "No\n";
}
return 0;
}
T3. Lab 杯
“ Lab \text{Lab} Lab 杯” 乒乓球赛就要在 PKU \text{PKU} PKU 的实验室之间举行了。人工智能实验室的学生都是乒乓球的狂热分子,都强烈希望代表实验室去比赛。但是有余名额限制,他们之中只能由一个人被选作代表。
为了让选择的过程公平,他们决定打一次单循环赛,每一对学生之间都打一场五局三胜的比赛。赢得最多比赛的人就将代表实验室去比赛。现在 Ava \text{Ava} Ava 手里有一份表,表里面记录了每一场比赛的比分。她应该让谁去比赛?
时间限制:1 s
内存限制:64 MB
- 输入
输入包含一组测试数据。
第一行包含 n n n( 2 ≤ n ≤ 100 2 ≤ n ≤ 100 2≤n≤100),表示实验室里学生的数目。
接下来给出一个 n × n n × n n×n 矩阵 A A A。矩阵的每一个元素都是 0 0 0、 1 1 1、 2 2 2、 3 3 3 中的一个。第 i i i 行第 j j j 列的元素 a i j a_{ij} aij 是第 i i i 个学生在和第 j j j 个学生的比赛中赢的局数。 a i j a_{ij} aij 和 a j i a_{ji} aji( i ≠ j i ≠ j i=j)正好有一个是 3 3 3,另外一个小于 3 3 3。矩阵的所有对角线元素都是 0 0 0。 - 输出
输出赢了最多比赛的学生的编号。如果有平分,选择编号最小的。 - 样例输入
4 0 0 3 2 3 0 3 1 2 2 0 2 3 3 3 0
- 样例输出
4
思路分析
此题考查题目信息提取的能力,以及打擂台思想,属于入门题。
按行统计第 i i i 个学生获胜的场数,即 3 3 3 的个数,然后比较所有学生的获胜场数,输出获胜场数最多的学生编号即可。
/*
* Name: T3.cpp
* Problem: Lab 杯
* Author: Teacher Gao.
* Date&Time: 2024/11/15 22:07
*/
#include <iostream>
using namespace std;
int main(){
int n, x;
int ans_id, ans_num = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
int tot = 0;
for (int j = 1; j <= n; j++) {
cin >> x;
if (x == 3) tot++;
}
if (tot > ans_num) {
ans_num = tot;
ans_id = i;
}
}
cout << ans_id;
return 0;
}
T4. 有趣的跳跃
一个长度为 n n n( n > 0 n>0 n>0)的序列中存在 “有趣的跳跃” 当且仅当相邻元素的差的绝对值经过排序后正好是从 1 1 1 到 ( n − 1 ) (n-1) (n−1)。例如, 1 4 2 3 1\ 4\ 2\ 3 1 4 2 3 存在 “有趣的跳跃”,因为差的绝对值分别为 3 , 2 , 1 3,2,1 3,2,1。当然,任何只包含单个元素的序列一定存在 “有趣的跳跃”。你需要写一个程序判定给定序列是否存在 “有趣的跳跃”。
时间限制:1 s
内存限制:64 MB
- 输入
一行,第一个数是 n n n( 0 < n < 3000 0 < n < 3000 0<n<3000),为序列长度,接下来有 n n n 个整数,依次为序列中各元素,各元素的绝对值均不超过 1 0 9 10^9 109。 - 输出
一行,若该序列存在 “有趣的跳跃”,输出Jolly
,否则输出Not jolly
。 - 样例输入
4 1 4 2 3
- 样例输出
Jolly
思路分析
此题考查桶的思想,属于入门题。
依次将相邻两个元素的差值
x
x
x 进行标记,在这个过程中,若
x
≥
n
x \ge n
x≥n 或者
x
x
x 已经被标记过,那么就可以确定该序列为 Not jolly
。注意差值
x
x
x 应取绝对值,因为输入序列并不保证递增。
/*
* Name: T4.cpp
* Problem: 有趣的跳跃
* Author: Teacher Gao.
* Date&Time: 2024/11/15 22:11
*/
#include <iostream>
#include <cmath>
using namespace std;
int main() {
int n, a[3005] = {0}, b[3005] = {0};
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 2; i <= n; i++) {
int x = abs(a[i] - a[i - 1]);
if (x >= n || b[x]) {
cout << "Not jolly";
return 0;
}
b[x]++;
}
cout << "Jolly";
return 0;
}
T5. 反反复复
Mo
\text{Mo}
Mo 和
Larry
\text{Larry}
Larry 发明了一种信息加密方法。他们首先决定好列数,然后将信息(只包含字母)从上往下依次填入各列,并在末尾补充一些随机字母使其成为一个完整的字母矩阵。例如,若信息是 There's no place like home on a snowy night
并且有
5
5
5 列,
Mo
\text{Mo}
Mo 会写成:
t o i o y
h p k n n
e l e a i
r a h s g
e c o n h
s e m o t
n l e w x
注意
Mo
\text{Mo}
Mo 只会填入字母,且全部是小写形式。在这个例子中,
Mo
\text{Mo}
Mo 用字母 x
填充了信息使之成为一个完整的矩阵,当然他使用任何字母都是可以的。
Mo
\text{Mo}
Mo 根据这个矩阵重写信息:首先从左到右写下第一行,然后从右到左写下第二行,再从左到右写下第三行
…
\dots
… 以此左右交替地从上到下写下各行字母,形成新的字符串。这样,例子中的信息就被加密为:toioynnkpheleaigshareconhtomesnlewx
。
你的工作是帮助 Larry \text{Larry} Larry 从加密后的信息中还原出原始信息(包括填充的字母)。
时间限制:1 s
内存限制:64 MB
- 输入
第一行包含一个整数(范围 2 2 2 到 20 20 20),表示使用的列数。
第二行是一个长度不超过 200 200 200 的字符串。 - 输出
一行,即原始信息。 - 样例输入
5 toioynnkpheleaigshareconhtomesnlewx
- 样例输出
theresnoplacelikehomeonasnowynightx
思路分析
此题考查字符串操作,属于入门题。
我们完全可以将这个字符串当成一个二维矩阵来处理,注意好下标变换即可。首先将字符串 s s s 中偶数行的子串进行翻转,然后按列进行输出。
/*
* Name: T5.cpp
* Problem: 反反复复
* Author: Teacher Gao.
* Date&Time: 2024/11/15 22:21
*/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int main()
{
int n;
char s[205];
cin >> n >> s;
int len = strlen(s);
// 翻转偶数行子串
for (int i = n; i < len; i += 2*n) {
reverse(s + i, s + i + n);
}
// 按列输出字符
for (int i = 0; i < n; i++) {
for (int j = i; j < len; j += n) {
cout << s[j];
}
}
return 0;
}