1

GESP认证C++编程真题解析 | 202403 五级

**​欢迎大家订阅我的专栏:算法题解:C++与Python实现
本专栏旨在帮助大家从基础到进阶 ,逐步提升编程能力,助力信息学竞赛备战!

专栏特色
1.经典算法练习:根据信息学竞赛大纲,精心挑选经典算法题目,提供清晰的代码实现与详细指导,帮助您夯实算法基础。
2.系统化学习路径:按照算法类别和难度分级,从基础到进阶,循序渐进,帮助您全面提升编程能力与算法思维。

适合人群:

  • 准备参加蓝桥杯、GESP、CSP-J、CSP-S等信息学竞赛的学生
  • 希望系统学习C++/Python编程的初学者
  • 想要提升算法与编程能力的编程爱好者

附上汇总帖:GESP认证C++编程真题解析 | 汇总


编程题

B3968 成绩排序

【题目来源】

洛谷:B3968 [GESP202403 五级] 成绩排序 - 洛谷

【题目描述】

有 名同学,每名同学有语文、数学、英语三科成绩。你需要按如下规则对所有同学的成绩从高到低排序:

  1. 比较总分,高者靠前;
  2. 如果总分相同,则比较语文和数学两科总分,高者靠前;
  3. 如果仍相同,则比较语文和数学两科的最高分,高者靠前;
  4. 如果仍相同,则二人并列。

你需要输出每位同学的排名,如遇 \(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
posted @ 2026-01-19 16:58  热爱编程的通信人  阅读(0)  评论(0)    收藏  举报