GESP认证C++编程真题解析 | 202403 五级
**欢迎大家订阅我的专栏:算法题解:C++与Python实现!
本专栏旨在帮助大家从基础到进阶 ,逐步提升编程能力,助力信息学竞赛备战!
专栏特色
1.经典算法练习:根据信息学竞赛大纲,精心挑选经典算法题目,提供清晰的代码实现与详细指导,帮助您夯实算法基础。
2.系统化学习路径:按照算法类别和难度分级,从基础到进阶,循序渐进,帮助您全面提升编程能力与算法思维。
适合人群:
- 准备参加蓝桥杯、GESP、CSP-J、CSP-S等信息学竞赛的学生
- 希望系统学习C++/Python编程的初学者
- 想要提升算法与编程能力的编程爱好者
附上汇总帖:GESP认证C++编程真题解析 | 汇总
编程题
B3968 成绩排序
【题目来源】
洛谷:B3968 [GESP202403 五级] 成绩排序 - 洛谷
【题目描述】
有 名同学,每名同学有语文、数学、英语三科成绩。你需要按如下规则对所有同学的成绩从高到低排序:
- 比较总分,高者靠前;
- 如果总分相同,则比较语文和数学两科总分,高者靠前;
- 如果仍相同,则比较语文和数学两科的最高分,高者靠前;
- 如果仍相同,则二人并列。
你需要输出每位同学的排名,如遇 \(x\) 人并列,则他们排名相同,并留空后面的 \(x-1\) 个名次。例如,有 \(3\) 名同学并列第 \(1\),则后一名同学自动成为第 \(4\) 名。
【输入】
第一行一个整数 \(N\),表示同学的人数。
接下来 \(N\) 行,每行三个非负整数 \(c_i,m_i,e_i\) 分别表示该名同学的语文、数学、英语成绩。
【输出】
输出 \(N\) 行,按输入同学的顺序,输出他们的排名。
注意:请不要按排名输出同学的序号,而是按同学的顺序输出他们各自的排名
【输入样例】
6
140 140 150
140 149 140
148 141 140
141 148 140
145 145 139
0 0 0
【输出样例】
1
3
4
4
2
6
【算法标签】
《洛谷 B3968 成绩排序》 #模拟# #排序# #GESP# #2024#
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n; // 学生人数
// 学生结构体,存储各科成绩和相关信息
struct Stu {
int yw, sx, yy; // 语文、数学、英语成绩
int tot; // 总分
int ys; // 语文+数学总分
int max_ys; // 语文和数学中的最高分
int id; // 学生编号
int rk; // 最终排名
};
Stu stu[10005]; // 学生数组
// 排序比较函数1:用于成绩排序
bool cmp(Stu x, Stu y) {
if (x.tot != y.tot) return x.tot > y.tot; // 规则1:总分高的在前
else if (x.ys != y.ys) return x.ys > y.ys; // 规则2:语文+数学高的在前
else if (x.max_ys != y.max_ys) return x.max_ys > y.max_ys; // 规则3:语文或数学单科高的在前
else return x.id < y.id; // 规则4:编号小的在前
}
// 排序比较函数2:用于按学生编号排序输出
bool cmp2(Stu x, Stu y) {
return x.id < y.id;
}
int main() {
cin >> n; // 输入学生人数
// 输入并处理每个学生的成绩数据
for (int i = 1; i <= n; i++) {
int ci, mi, ei;
cin >> ci >> mi >> ei;
stu[i].id = i; // 记录学生编号
stu[i].yw = ci; // 语文成绩
stu[i].sx = mi; // 数学成绩
stu[i].yy = ei; // 英语成绩
stu[i].ys = ci + mi; // 语文+数学总分
stu[i].max_ys = max(ci, mi); // 语文或数学最高分
stu[i].tot = ci + mi + ei; // 三科总分
}
// 第一次排序:按成绩规则排序
sort(stu + 1, stu + n + 1, cmp);
int cnt = 1; // 排名计数器
// 计算每个学生的实际排名(处理并列情况)
for (int i = 1; i <= n; i++) {
// 检查是否与前一名学生成绩完全相同
if (i > 1 && stu[i].tot == stu[i-1].tot &&
stu[i].ys == stu[i-1].ys &&
stu[i].max_ys == stu[i-1].max_ys) {
stu[i].rk = stu[i-1].rk; // 并列排名
} else {
stu[i].rk = cnt; // 新排名
}
cnt++; // 排名计数器递增
}
// 第二次排序:按学生编号排序,方便输出
sort(stu + 1, stu + n + 1, cmp2);
// 输出每个学生的排名
for (int i = 1; i <= n; i++) {
cout << stu[i].rk << endl;
}
return 0;
}
【运行结果】
6
140 140 150
140 149 140
148 141 140
141 148 140
145 145 139
0 0 0
1
3
4
4
2
6
B3969 B-smooth 数
【题目来源】
洛谷:B3969 [GESP202403 五级] B-smooth 数 - 洛谷
【题目描述】
小杨同学想寻找一种名为 \(B\)-smooth 数的正整数。
如果一个正整数的最大质因子不超过 \(B\),则该正整数为 \(B\)-smooth 数。
小杨同学想知道,对于给定的 \(n\) 和 \(B\),有多少个不超过 \(n\) 的 \(B\)-smooth 数。
【输入】
第一行包含两个正整数 \(n\) 和 \(B\),含义如题面所示。
【输出】
输出一个非负整数,表示不超过 \(n\) 的 \(B\)-smooth 数的数量。
【输入样例】
10 3
【输出样例】
7
【算法标签】
《洛谷 B3969 [GESP202403 五级] B-smooth 数》 #素数判断,质数,筛法# #GESP# #2024#
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n, B, ans, cnt;
int maxPrime[1000005], prime[1000005], notPrime[1000005];
// 欧拉筛法预处理所有数的最大质因子
void getPrime() {
prime[1] = 1; // 1不是质数
maxPrime[1] = 1; // 1的最大质因子设为1
for (int i = 2; i <= 1000000; i++) {
if (!notPrime[i]) { // 如果是质数
prime[cnt++] = i; // 存入质数数组
maxPrime[i] = i; // 质数的最大质因子是其本身
}
// 用当前数和已知质数筛去合数
for (int j = 0; j < cnt && i * prime[j] <= 1000000; j++) {
notPrime[i * prime[j]] = 1; // 标记为合数
// 计算i*prime[j]的最大质因子
maxPrime[i * prime[j]] = max(prime[j], maxPrime[i]);
// 关键优化:保证每个合数只被最小质因子筛一次
if (i % prime[j] == 0) {
break;
}
}
}
}
int main() {
cin >> n >> B; // 输入范围n和阈值B
getPrime(); // 预处理所有数的最大质因子
// 统计1到n中最大质因子不超过B的数的个数
for (int i = 1; i <= n; i++) {
if (maxPrime[i] <= B) {
ans++;
}
}
cout << ans << endl; // 输出结果
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int n, B, cnt, cur;
int maxPrime[1000005], prime[1000005];
bool flag[1000005];
// 埃拉托斯特尼筛法(埃氏筛)预处理最大质因子
void getPrime() {
memset(flag, true, sizeof(flag)); // 初始化为true,表示都是质数
flag[0] = flag[1] = false; // 0和1不是质数
maxPrime[1] = 1; // 1的最大质因子设为1
for (int i = 2; i <= n; i++) {
if (flag[i]) { // 如果i是质数
prime[++cur] = i; // 存入质数数组
maxPrime[i] = i; // 质数的最大质因子是其本身
// 标记i的所有倍数为合数
for (int j = 2 * i; j <= n; j += i) {
flag[j] = false; // 标记为合数
maxPrime[j] = i; // 更新其最大质因子为i
}
}
}
}
int main() {
cin >> n >> B; // 输入范围n和阈值B
getPrime(); // 预处理最大质因子
// 统计1到n中最大质因子不超过B的数的个数
for (int i = 1; i <= n; i++) {
if (maxPrime[i] <= B) {
cnt++;
}
}
cout << cnt << endl; // 输出结果
return 0;
}
【运行结果】
10 3
7

浙公网安备 33010602011771号