信奥刷题站
GESP 认证 5级2025-09

2025年9月 GESP C++ 5级

题量
26 题
客观题
24 题
建议时长
60 分钟
卷面总分
100 分

2025年9月 GESP C++ 5级认证考试真题(含编程操作题部分)

开始整卷模拟计时作答 · 交卷即时判分 · 错题自动进错题本(需登录)2 道编程大题:在线只判客观题,编程题请自行前往洛谷等 OJ 提交验证

// questions

题目预览

1
单选题2

以下哪种情况使用链表比数组更合适?

A

数据量固定且读多写少

B

需要频繁在中间或开头插入、删除元素

C

需要高效随机访问元素

D

存储空间必须连续

2
单选题2

函数 removeElements 删除单链表中所有结点值等于 valvalval 的结点,并返回新的头结点,其中链表头结点为 headheadhead,则横线处填写( )。

// 结点结构体
struct Node {
    int val;
    Node* next;
    Node() : val(0), next(nullptr) {}
    Node(int x) : val(x), next(nullptr) {}
    Node(int x, Node *next) : val(x), next(next) {}
};
Node* removeElements(Node* head, int val) {
    Node dummy(0, head); // 哑结点,统一处理头结点
    Node* cur = &dummy;
    while (cur->next) {
        if (cur->next->val == val) {
            _______________________ // 在此填入代码
        }
        else {
            cur = cur->next;
        }
    }
    return dummy.next;
}
A
Node* del = cur;
cur = del->next;
delete del;
B
Node* del = cur->next;
cur->next = del;
delete del;
C
Node* del = cur->next;
cur->next = del->next;
delete del;
D
Node* del = cur->next;
delete del;
cur->next = del->next;
3
单选题2

函数 hasCycle 采用 Floyd 快慢指针法判断一个单链表中是否存在环,链表的头节点为 head ,即用两个指针在链表上前进: slow 每次走 111 步, fast 每次走 222 步,若存在环, fast 终会追上 slow (相遇);若无环, fast 会先到达 nullptr ,则横线上应填写( )。

struct Node {
    int val;
    Node *next;
    Node(int x) : val(x), next(nullptr) {}
};
bool hasCycle(Node *head) {
    if (!head || !head->next)
        return false;
    Node* slow = head;
    Node* fast = head->next;
    while (fast && fast->next) {
        if (slow == fast) return true;
        _______________________ // 在此填入代码
    }
    return false;
}
A
slow = slow->next;
fast = fast->next->next;
B
slow = fast->next;
fast = slow->next->next;
C
slow = slow->next;
fast = slow->next->next;
D
slow = fast->next;
fast = fast->next->next;
4
单选题2

函数 isPerfectNumber 判断一个正整数是否为完全数(该数是否即等于它的真因⼦之和),则横线上应填写( )。一个正整数 nnn 的真因⼦包括所有小于 nnn 的正因⼦,如 282828 的真因⼦为 111, 222, 444, 777, 141414

bool isPerfectNumber(int n) {
    if(n <= 1) return false;
    int sum = 1;
    for(int i = 2; ______; i++) {
        if(n % i == 0) {
            sum += i;
            if(i != n/i) sum += n/i;
        }
    }
    return sum == n;
}
A

i <= n

B

i*i <= n

C

i <= n/2

D

i < n

5
单选题2

以下代码计算两个正整数的最大公约数 (GCD),横线上应填写( )。

int gcd0(int a, int b) {
    if (a < b) {
        swap(a, b);
    }
    while(b != 0) {
        int temp = a % b;
        a = b;
        b = temp;
    }
    return ______;
}
A

b

B

a

C

temp

D

a * b

6
单选题2

函数 sieve 实现埃拉托斯特尼筛法(埃氏筛),横线处应填入( )。

vector<bool> sieve(int n) {
    vector<bool> is_prime(n+1, true);
    is_prime[0] = is_prime[1] = false;
    for(int i = 2; i <= n; i++) {
        if(is_prime[i]) {
            for(int j = ______; j <= n; j += i) {
                is_prime[j] = false;
            }
        }
    }
    return is_prime;
}
A

i

B

i+1

C

i*2

D

i*i

7
单选题2

函数 linearSieve 实现线性筛法(欧拉筛),横线处应填入( )。

vector<int> linearSieve(int n) {
    vector<bool> is_prime(n+1, true);
    vector<int> primes;
    for(int i = 2; i <= n; i++) {
        if(is_prime[i]) primes.push_back(i);
        for(int p : primes) {
            if(p * i > n) break;
            is_prime[p * i] = false;
            if(________) break;
        }
    }
    return primes;
}
A

i % p == 0

B

p % i == 0

C

i == p

D

i * p == n

8
单选题2

关于埃氏筛和线性筛的比较,下列说法错误的是( )。

A

埃氏筛可能会对同一个合数进行多次标记

B

线性筛的理论时间复杂度更优,所以线性筛的速度往往优于埃氏筛

C

线性筛保证每个合数只被其最小质因子筛到一次

D

对于常见范围(n≤107n \leq 10^7n107),埃氏筛因实现简单,常数较小,其速度往往优于线性筛

9
单选题2

唯一分解定理描述的是( )。

A

每个整数都能表示为任意素数的乘积

B

每个大于 111 的整数能唯一分解为素数幂乘积(忽略顺序)

C

合数不能分解为素数乘积

D

素数只有两个因子:111 和自身

10
单选题2

给定一个 n×nn \times nn×n 的矩阵 matrixmatrixmatrix,矩阵的每一行和每一列都按升序排列。函数 countLE 返回矩阵中第 kkk 小的元素,则两处横线上应分别填写( )。

// 统计矩阵中 <= x 的元素个数:从左下角开始
int countLE(const vector<vector<int>>& matrix, int x) {
    int n = (int)matrix.size();
    int i = n - 1, j = 0, cnt = 0;
    while (i >= 0 && j < n) {
        if (matrix[i][j] <= x) {
            cnt += i + 1;
            ++j;
        }
        else {
            --i;
        }
    }
    return cnt;
}
int kthSmallest(vector<vector<int>>& matrix, int k) {
    int n = (int)matrix.size();
    int lo = matrix[0][0];
    int hi = matrix[n - 1][n - 1];
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;
        if (countLE(matrix, mid) >= k) {
            ________________ // 在此处填入代码
        } else {
            ________________ // 在此处填入代码
        }
    }
    return lo;
}
A
hi = mid - 1;
lo = mid + 1;
B
hi = mid;
lo = mid;
C
hi = mid;
lo = mid + 1;
D
hi = mid + 1;
lo = mid;
11
单选题2

下述 C++ 代码实现了快速排序算法,下面说法错误的是( )。

int partition(vector<int>& arr, int low, int high) {
    int i = low, j = high;
    int pivot = arr[low]; // 以首元素为基准
    while (i < j) {
        while (i < j && arr[j] >= pivot) j--; //从右往左查找
        while (i < j && arr[i] <= pivot) i++; //从左往右查找
        if (i < j) swap(arr[i], arr[j]);
    }
    swap(arr[i], arr[low]);
    return i;
}
void quickSort(vector<int>& arr, int low, int high) {
    if (low >= high) return;
    int p = partition(arr, low, high);
    quickSort(arr, low, p - 1);
    quickSort(arr, p + 1, high);
}
A

快速排序之所以叫“快速”,是因为它在平均情况下运行速度较快,常数小、就地排序,实践中通常比归并排序更高效。

B

在平均情况下,划分的递归层数为 O(log⁡n)O(\log n)O(logn),每层中的总循环数为 O(n)O(n)O(n),总时间为 O(nlog⁡n)O(n \log n)O(nlogn)

C

在最差情况下,每轮划分操作都将长度为 nnn 的数组划分为长度为 000n−1n-1n1 的两个子数组,此时递归层数达到 O(n)O(n)O(n),每层中的循环数为 O(n)O(n)O(n),总时间为 O(n2)O(n^2)O(n2)

D

划分函数 partition 中“从右往左查找”与“从左往右查找”的顺序可以交换。

12
单选题2

下述 C++ 代码实现了归并排序算法,则横线上应填写( )。

void merge(vector<int> &nums, int left, int mid, int right) {
    // 左子数组区间为 [left, mid], 右子数组区间为 [mid+1, right]
    vector<int> tmp(right - left + 1);
    int i = left, j = mid + 1, k = 0;
    while (i <= mid && j <= right) {
        if (nums[i] <= nums[j])
            tmp[k++] = nums[i++];
        else
            tmp[k++] = nums[j++];
    }
    while (i <= mid) {
        tmp[k++] = nums[i++];
    }
    while (________) { // 在此处填入代码
        tmp[k++] = nums[j++];
    }
    for (k = 0; k < tmp.size(); k++) {
        nums[left + k] = tmp[k];
    }
}
void mergeSort(vector<int> &nums, int left, int right) {
    if (left >= right)
        return;
    int mid = (left + right) / 2;
    mergeSort(nums, left, mid);
    mergeSort(nums, mid + 1, right);
    merge(nums, left, mid, right);
}
A

i < mid

B

j < right

C

i <= mid

D

j <= right

13
单选题2

假设你是一家电影院的排片经理,只有一个放映厅。你有一个电影列表 moviesmoviesmovies,其中 movies[i]=[starti,endi]movies[i] = [start_i, end_i]movies[i]=[starti,endi] 表示第 iii 部电影的开始和结束时间。请你找出最多能安排多少部不重叠的电影,则横线上应分别填写的代码为( )。

int maxMovies(vector<vector<int>>& movies) {
    if (movies.empty()) return 0;
    sort(movies.begin(), movies.end(), [](const vector<int>& a, const vector<int>& b) {
        return ______; // 在此处填入代码
    });
    int count = 1;
    int lastEnd = movies[0][1];
    for (int i = 1; i < movies.size(); i++) {
        if (movies[i][0] >= lastEnd) {
            count++;
            ______ = movies[i][1]; // 在此处填入代码
        }
    }
    return count;
}
A

a[0] < b[0]lastEnd

B

a[1] < b[1]lastEnd

C

a[0] < b[0]movies[i][0]

D

a[1] < b[1]movies[i][0]

14
单选题2

给定一个整数数组 numsnumsnums,下面代码找到一个具有最大和的连续子数组,并返回该最大和。则下面说法错误的是( )。

int crossSum(vector<int>& nums, int left, int mid, int right) {
    int leftSum = INT_MIN, rightSum = INT_MIN;
    int sum = 0;
    for (int i = mid; i >= left; i--) {
        sum += nums[i];
        leftSum = max(leftSum, sum);
    }
    sum = 0;
    for (int i = mid + 1; i <= right; i++) {
        sum += nums[i];
        rightSum = max(rightSum, sum);
    }
    return leftSum + rightSum;
}
int helper(vector<int>& nums, int left, int right) {
    if (left == right)
        return nums[left];
    int mid = left + (right - left) / 2;
    int leftMax = helper(nums, left, mid);
    int rightMax = helper(nums, mid + 1, right);
    int crossMax = crossSum(nums, left, mid, right);
    return max({leftMax, rightMax, crossMax});
}
int maxSubArray(vector<int>& nums) {
    return helper(nums, 0, nums.size() - 1);
}
A

上述代码采用分治算法实现

B

上述代码采用贪心算法

C

上述代码时间复杂度为 O(nlog⁡n)O(n \log n)O(nlogn)

D

上述代码采用递归方式实现

15
单选题2

给定一个由非负整数组成的数组 digits ,表示一个非负整数的各位数字,其中最高位在数组首位,且 digits 不含前导 000 (除非是 000 本身)。下面代码对该整数执行 +1+1+1 操作,并返回结果数组,则横线上应填写( )。

vector<int> plusOne(vector<int>& digits) {
    for (int i = (int)digits.size() - 1; i >= 0; --i) {
        if (digits[i] < 9) {
            digits[i] += 1;
            return digits;
        }
        ________________ // 在此处填入代码
    }
    digits.insert(digits.begin(), 1);
    return digits;
}
A

digits[i] = 0;

B

digits[i] = 9;

C

digits[i] = 1;

D

digits[i] = 10;

16
判断题2

基于下面定义的函数,通过判断 isDivisibleBy9(n) == isDigitSumDivisibleBy9(n) 代码可验算如果一个数能被 999 整除,则它的各位数字之和能被 999 整除。

bool isDivisibleBy9(int n) {
    return n % 9 == 0;
}
bool isDigitSumDivisibleBy9(int n) {
    int sum = 0;
    string numStr = to_string(n);
    for (char c : numStr) {
        sum += (c - '0');
    }
    return sum % 9 == 0;
}
17
判断题2

假设函数 gcd() 能正确求两个正整数的最大公约数,则下面的 findMusicalPattern(4, 6) 函数返回 222

void findMusicalPattern(int rhythm1, int rhythm2) {
    int commonDivisor = gcd(rhythm1, rhythm2);
    int patternLength = (rhythm1 * rhythm2) / commonDivisor;
    return patternLength;
}
18
判断题2

下面递归实现的斐波那契数列的时间复杂度为 。

long long fib_memo(int n, long long memo[]) {
    if (n <= 1) return n;
    if (memo[n] != -1) return memo[n];
    memo[n] = fib_memo(n - 1, memo) + fib_memo(n - 2, memo);
    return memo[n];
}
int main() {
    int n = 40;
    long long memo[100];
    fill_n(memo, 100, -1);
    long long result2 = fib_memo(n, memo);
    return 0;
}
19
判断题2

链表通过更改指针实现高效的结点插入与删除,但结点访问效率低、占用内存较多,且对缓存利用不友好。

20
判断题2

二分查找依赖数据的有序性,通过循环逐步缩减一半搜索区间来进行查找,且仅适用于数组或基于数组实现的数据结构。

21
判断题2

线性筛关键是“每个合数只会被最小质因⼦筛到一次”,因此为 O(n)O(n)O(n)

22
判断题2

快速排序和归并排序都是稳定的排序算法。

23
判断题2

所有递归算法都可以转换为迭代算法。

24
判断题2

贪心算法总能得到全局最优解。

GESP 编程操作题
25
编程题25

试题名称:数字选取

时间限制:1.0 s | 内存限制:512.0 MB

题目描述

给定正整数 nnn,现在有 1,2,…,n1,2,\ldots,n1,2,,n 共计 nnn 个整数。你需要从这 nnn 个整数中选取一些整数,使得所选取的整数中任意两个不同的整数均互质(也就是说,这两个整数的最大公因数为 111)。请你最大化所选取整数的数量。

例如,当 n=9n=9n=9 时,可以选择 1,5,7,8,91,5,7,8,91,5,7,8,9 共计 555 个整数。可以验证不存在数量更多的选取整数的方案。

输入格式

一行,一个正整数 nnn,表示给定的正整数。

输出格式

一行,一个正整数,表示所选取整数的最大数量。

样例输入 #1

6

样例输出 #1

4

样例输入 #2

9

样例输出 #2

5

说明/提示

对于 40%40\%40% 的测试点,保证 1≤n≤10001\le n\le 10001n1000

对于所有测试点,保证 1≤n≤1051\le n\le 10^51n105

本题为编程大题:请复制题面到洛谷 / GESP OJ 等平台编写并提交代码(本站不判分)
26
编程题25

试题名称:有趣的数字和

时间限制:200.0 s | 内存限制:512.0 MB

题目描述

如果一个正整数的二进制表示包含奇数个 111,那么小 A 就会认为这个正整数是有趣的。

例如,777 的二进制表示为 (111)2(111)_2(111)2,包含 111 的个数为 333 个,所以 777 是有趣的。但是 9=(1001)29=(1001)_29=(1001)2 包含 222111,所以 999 不是有趣的。

给定正整数 l,rl,rl,r,请你统计满足 l≤n≤rl\le n\le rlnr 的有趣的整数 nnn 之和。

输入格式

一行,两个正整数 l,rl,rl,r,表示给定的正整数。

输出格式

一行,一个正整数,表示 l,rl,rl,r 之间有趣的整数之和。

样例输入 #1

3 8

样例输出 #1

19

样例输入 #2

65 36248

样例输出 #2

328505490

说明/提示

【数据范围】

对于 40%40\%40% 的测试点,保证 1≤l≤r≤1041\le l\le r\le 10^41lr104

对于另外 30%30\%30% 的测试点,保证 l=1l=1l=1 并且 r=2k−1r=2^k-1r=2k1,其中 kkk 是大于 111 的正整数。

对于所有测试点,保证 1≤l≤r≤1091 \le l\le r\le 10^91lr109

【提示】

由于本题的数据范围较大,整数类型请使用 long long。

本题为编程大题:请复制题面到洛谷 / GESP OJ 等平台编写并提交代码(本站不判分)