2021 年 3 月青少年软编等考 C 语言二级真题解析

T1. 与指定数字相同的数的个数

题目链接:SOJ D1043

输出一个整数序列中与指定数字相同的数的个数。

时间限制:1 s
内存限制:64 MB

  • 输入
    输入包含三行:
    第一行为 n n n,表示整数序列的长度( n ≤ 100 n \le 100 n100)。
    第二行为 n n n 个整数,整数之间以一个空格分开。
    第三行包含一个整数,为指定的整数 m m m
  • 输出
    输出为 n n n 个数中与 m m m 相同的数的个数。
  • 样例输入
    3
    2 3 2
    2
    
  • 样例输出
    2
    

思路分析

此题考查一维数组的查询操作,属于入门题。

此题只需要将输入的 n n n 个整数存储到数组 a 中,然后在数组 a 中查询 m 出现的次数即可。这里可以设置一个计数器变量 tot 进行统计,注意 tot 需要初始化为 0 0 0。之所以需要用到数组,是因为此题将需要查询的数放在了最后进行输入。

/*
 * Name: T1.cpp
 * Problem: 与指定数字相同的数的个数
 * Author: Teacher Gao.
 * Date&Time: 2024/03/26 02:33
 */

#include <iostream>

using namespace std;

int main()
{
	int n, m, a[105];
	
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	cin >> m;

	int tot = 0;
	for (int i = 1; i <= n; i++) {
		if (a[i] == m) {
			tot++;
		}
	}

	cout << tot << endl;

	return 0;
}

T2. 合法 C 标识符

题目链接:SOJ D1044

给定一个不包含空白符的字符串,请判断是否是 C 语言合法的标识符,题目保证这些字符串一定不是 C 语言的保留字。

C 语言标识符要求:

  1. 非保留字。
  2. 只包含字母、数字及下划线(_)。
  3. 不能以数字开头。

时间限制:1 s
内存限制:64 MB

  • 输入
    一行,包含一个字符串,字符串中不包含任何空白字符,且长度不大于 20 20 20
  • 输出
    一行,如果它是 C 语言的合法标识符,则输出 yes,否则输出 no
  • 样例输入
    RKPEGX9R;TWyYcp
    
  • 样例输出
    no
    

思路分析

此题考查字符串的遍历与字符检测,属于入门题。

此题只需要按照题意对输入的字符串进行遍历检测即可。注意,确定一个标识符合法需要将整个标识符字符串遍历结束,确定没有违反规定才可以。而确定一个标识符非法只需要在遍历过程中检测出一个不合法的字符即可。

/*
 * Name: T2.cpp
 * Problem: 合法 C 标识符
 * Author: Teacher Gao.
 * Date&Time: 2024/03/26 02:36
 */

#include <iostream>
#include <string>

using namespace std;

int main()
{
	string str;
	cin >> str;

	int len = str.length();
	for (int i = 0; i < len; i++)
		str[i] = tolower(str[i]);

	if ((str[0] < 'a' || 'z' < str[0]) && str[0] != '_') {
		cout << "no" << endl;
		return 0;
	}
	
	for (int i = 1; i < len; i++) {
		if ('0' <= str[i] && str[i] <= '9')
			continue;
		if ('a' <= str[i] && str[i] <= 'z')
			continue;
		if ('_' == str[i])
			continue;

		cout << "no" << endl;
		return 0;
	}

	cout << "yes" << endl;

	return 0;
}

T3. 计算鞍点

题目链接:SOJ D1045

给定一个 5 × 5 5×5 5×5 的矩阵,每行只有一个最大值,每列只有一个最小值,寻找这个矩阵的鞍点。鞍点指的是矩阵中的一个元素,它是所在行的最大值,并且是所在列的最小值。

例如:在下面的例子中,第 4 4 4 行第 1 1 1 列的元素就是鞍点,值为 8 8 8

11  3  5  6  9
12  4  7  8 10
10  5  6  9 11
 8  6  4  7  2
15 10 11 20 25

时间限制:1 s
内存限制:64 MB

  • 输入
    输入包含一个 5 5 5 5 5 5 列的矩阵。
  • 输出
    如果存在鞍点,输出鞍点所在的行、列及其值,如果不存在,输出 not found
  • 样例输入
    11  3  5  6  9
    12  4  7  8 10
    10  5  6  9 11
     8  6  4  7  2
    15 10 11 20 25
    
  • 样例输出
    4 1 8
    

思路分析

此题考察二维数组的应用,难度一般。

可以采用标记法,先将每行的最大值进行标记,然后将每列的最小值进行标记。然后检测标记数组,若某个位置被标记了两次,则该位置就是鞍点。

/*
 * Name: T3.cpp
 * Problem: 计算鞍点
 * Author: Teacher Gao.
 * Date&Time: 2024/03/26 02:51
 */

#include <iostream>

using namespace std;

int main()
{
	int n, m;
	int a[10][10], b[10][10] = {0};
	
    for (int i = 1; i <= 5; i++)
		for (int j = 1; j <= 5; j++)
			cin >> a[i][j];
    
    for (int i = 1; i <= 5; i++) {
        int tmp = 0, tmpj = 0;
        for (int j = 1; j <= 5; j++) {
            if (tmp < a[i][j]) {
				tmp = a[i][j];
				tmpj = j;
			}
        }
        b[i][tmpj]++;
    }
    
    for (int j = 1; j <= 5; j++) {
        int tmp = 1e9, tmpi = 0;
        for (int i = 1; i <= 5; i++) {
            if (tmp > a[i][j]) {
				tmp = a[i][j];
				tmpi = i;
			}
        }
        b[tmpi][j]++;
    }
      
    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j <= 5; j++) {
            if (2 == b[i][j]) {
                cout << i << " " << j << " " << a[i][j] << endl;
                return 0;
            }
        }
    }

    cout << "not found";
    
    return 0;
}

T4. 谁考了第 k 名

题目链接:SOJ D1046

在一次考试中,每个学生的成绩都不相同,现知道了每个学生的学号和成绩,求考第 k k k 名学生的学号和成绩。

时间限制:1 s
内存限制:64 MB

  • 输入
    第一行有两个整数,分别是学生的人数 n n n,所求的目标名次 k k k 1 ≤ k ≤ n ≤ 100 1 \le k \le n \le 100 1kn100
    其后有 n n n 行数据,每行包括一个学号(整数)和一个成绩(浮点数),中间用一个空格分隔。
  • 输出
    输出第 k k k 名学生的学号和成绩,中间用空格分隔。请用 %g 输出成绩。
  • 样例输入
    5 3
    90788001 67.8
    90788002 90.3
    90788003 61
    90788004 68.4
    90788005 73.9
    
  • 样例输出
    90788004 68.4
    

思路分析

此题考察排序算法,难度一般。

由于数据量不大,可以采用任意 O ( n 2 ) O(n^2) O(n2) 的排序算法,更好的方法是采用结构体排序,结合 sort 函数来使用。由于大纲描述较为模糊,并未明确表示二级考察结构体,在六级中提到 “掌握数据结构及结构的概念”,因此这里并没有采用结构体排序的写法,而是采用了冒泡排序。

/*
 * Name: T4.cpp
 * Problem: 谁考了第 k 名
 * Author: Teacher Gao.
 * Date&Time: 2024/03/26 03:11
 */

#include <cstdio>
#include <algorithm>

using namespace std;

int main()
{
	int n, k, a[105];
	double b[105];

	scanf("%d%d", &n, &k);
	for (int i = 1; i <= n; i++)
		scanf("%d%lf", &a[i], &b[i]);
    
    for (int i = 1; i < n; i++) {
        bool flag = true;
        for (int j = 1; j <= n - i; j++) {
            if (b[j] < b[j + 1]) {
				swap(b[j], b[j + 1]);
				swap(a[j], a[j + 1]);
				flag = false;
			}
        }

		if (flag) break;
    }

    printf("%d %g", a[k], b[k]);
    
    return 0;
}

T5. 石头剪刀布

题目链接:SOJ D1047

石头剪刀布是常见的猜拳游戏。石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一样,则不分胜负。

一天,小 A A A 和小 B B B 正好在玩石头剪刀布。已知他们的出拳都是有周期性规律的,比如:“石头 - 布 - 石头 - 剪刀 - 石头 - 布 - 石头 - 剪刀 . . . ... ...”,就是以 “石头 - 布 - 石头 - 剪刀” 为周期不断循环的。请问,小 A A A 和小 B B B 比了 n n n 轮之后,谁赢的轮数多?

时间限制:1 s
内存限制:64 MB

  • 输入
    输入包含三行。
    第一行包含三个整数: n , n a , n b n, na, nb n,na,nb,分别表示比了 n n n 轮,小 A A A 出拳的周期长度,小 B B B 出拳的周期长度。 0 < n , n a , n b < 100 0 < n, na, nb < 100 0<n,na,nb<100
    第二行包含 n a na na 个整数,表示小 A A A 出拳的规律。
    第三行包含 n b nb nb 个整数,表示小 B B B 出拳的规律。
    其中, 0 0 0 表示 “石头”, 2 2 2 表示 “剪刀”, 5 5 5 表示 “布”。相邻两个整数之间用单个空格隔开。
  • 输出
    输出一行,如果小 A A A 赢的轮数多,输出 A;如果小 B B B 赢的轮数多,输出 B;如果两人打平,输出 draw
  • 样例输入
    10 3 4
    0 2 5
    0 5 0 2
    
  • 样例输出
    A
    
  • 提示
    对于样例数据,猜拳过程为:
    A: 0 2 5 0 2 5 0 2 5 0
    B: 0 5 0 2 0 5 0 2 0 5
    

A A A 赢了 4 4 4 轮, B B B 赢了 2 2 2 轮,双方打平 4 4 4 轮,所以 A A A 赢的轮数多。

思路分析

此题考察数组的灵活应用,难度一般。

可以在输入结束后分别将 a[]b[] 按照给定出拳规律重复存储,直到存储够 n n n 项为止,然后依次对比每一次出拳,进而统计出获胜者。

也可以不进行重复存储,直接用下标对出拳周期 n a na na n b nb nb 分别取余,得到对应的出拳结果。需要注意的是,这种方法需要将出拳规律存储在下标 0 ∼ n a − 1 0 \sim na-1 0na1 0 ∼ n b − 1 0 \sim nb-1 0nb1 范围内。

至于比较出拳结果,可以封装成函数,使得逻辑结构更清晰。当函数返回 0 0 0 时表示平局; − 1 -1 1 表示小 A A A 负; 1 1 1 表示小 A A A 胜。在主函数内将该函数的返回值进行累加,若总数为正,则小 A A A 胜;总数为负,表示小 B B B 胜;否则表示平局。

/*
 * Name: T5.cpp
 * Problem: 石头剪刀布
 * Author: Teacher Gao.
 * Date&Time: 2024/05/26 15:42
 */

#include <iostream>

using namespace std;

int check(int a, int b)
{
	if (a == b) return 0;
	
	if (a == 2 && b == 0) return -1;
	if (a == 5 && b == 2) return -1;
	if (a == 0 && b == 5) return -1;
	
	return 1;
}

int main()
{
	int n, na, nb, tot = 0;
	int a[105], b[105];
	
	cin >> n >> na >> nb;
	for (int i = 0; i < na; i++) cin >> a[i];
	for (int i = 0; i < nb; i++) cin >> b[i];
	
	for (int i = 0; i < n; i++)
		tot += check(a[i%na], b[i%nb]);

	if (tot > 0) cout << 'A' << endl;
	else if (tot < 0) cout << 'B' << endl;
	else cout << "draw" << endl;

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南朔 Clancy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值