试卷总分:100分


选择题 15题 30分

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15


判断题 10题 20分

16 17 18 19 20 21 22 23 24 25


编程题 2题 50分

26 27

E1088 CCF-GESP编程能力等级认证-C++ -2026-09 CCF-GESP C++五级真题-考试

选择题 共15道

01

小杨用单链表保存任务序列,并同时维护头指针head 和尾指针tail。在链表非空且已知tail 的情况下,在表尾插入新结点的时间复杂度是()。

struct Node {
	int value;
	Node *next;
};
Node *head ;
Node *tail;
2分
登录后查看选项
02

在不带哨兵结点的双向链表中,结点p 既不是头结点也不是尾结点。删除p 的正确代码是()。

struct Node {
	int value;
	Node *prev;
	Node *next;
};
2分
登录后查看选项
03

下面函数使用快慢指针查找单链表的中间结点。横线处应填写()。

struct Node {
	int value;
	Node *next;
};
Node *middle(Node *head) {
	Node *slow = head;
	Node *fast = head;
	while (fast != nullptr && fast->next != nullptr) {
		slow = slow->next;
		_______________
	}
	return slow;
}
2分
登录后查看选项
04

函数gcd(int a , int b) 定义如下,则gcd(105 , 45) 的结果是()。

int gcd(int a , int b) {
	return b == 0 ? a : gcd(b , a % b);
}
2分
登录后查看选项
05

下面函数用于判断正整数n 是否为质数。横线处的最佳写法是()。

bool isPrime(int n) {
	if (n < 2)
		return false ;
	for (int i = 2;_______; i++) {
		if (n % i == 0)
			return false ;
	}
	return true ;
}
2分
登录后查看选项
06

下面代码实现线性筛法。为了保证每个合数只被其最小质因子筛去一次,横线处应填写()。

vector<int> linearSieve(int n) {
	vector<bool> composite(n + 1 , false);
	vector<int> primes ;
	for (int i = 2; i <= n ; i++) {
		if (!composite [i])
			primes .push_back(i);
		for (int p : primes) {
			if ((long long)i * p > n)
				break;
			composite [i * p] = true ;
			if (__________)
				break;
		}
	}
	return primes ;
}
2分
登录后查看选项
07

根据唯一分解定理,整数的正确质因数分解是()。

2分
登录后查看选项
08

函数f (int n) 定义如下,则f (4) 的结果是()。

int f (int n) {
	if (n == 1)
		return 1;
	return n + f (n - 1);
}
2分
登录后查看选项
09

在升序数组中查找第一个严格大于x 的元素位置,下面代码中的横线应填写()。

int upperBound(const vector<int> &a , int x) {
	int l = 0 , r = (int)a .size();
	while (l < r) {
		int mid = l + (r - l) / 2;
		if ( __________ ) {
			l = mid + 1;
		} else {
			r = mid ;
		}
	}
	return l;
}
2分
登录后查看选项
10

小杨需要把若干箱货物按原顺序分配到days 天中,每天运输连续的若干箱,求能够完成任务的最小载重量。函数check(cap) 判断载重量为cap 时能否在规定天数内运完。横线处应填写()。

long long l = maxWeight;
long long r = totalWeight;
while (l < r) {
	long long mid = l + (r - l) / 2;
	if (check(mid)) {
		_______________ 
	} else {
		_______________
	}
}
cout << l;
2分
登录后查看选项
11

下面是归并排序中合并两个有序区间(升序排序)的部分代码。若希望排序保持稳定,横线处应填写()。

while (i <= mid && j <= right) {
	if (_______________) {
		temp .push_back(a [i++]);
	} else {
		temp .push_back(a [j++]);
	}
}
2分
登录后查看选项
12

下面快速排序的划分函数以a [right] 为枢轴,并把不大于枢轴的元素移动到左侧。横线处应填写()。

int partition(int a [], int left , int right) {
	int pivot = a [right];
	int i = left - 1;
	for (int j = left ; j < right ; j++) {
		if (_________________) {
			i++;
			swap(a [i], a [j]);
		}
	}
	swap(a [i + 1], a [right]);
	return i + 1;
}
2分
登录后查看选项
13

小杨要在一个教室安排尽可能多场活动,每场活动具有开始时间start 和结束时间end 。采用贪心算法时,正确的选择策略是()。

struct Activity {
	int start ;
	int end ;
};
2分
登录后查看选项
14

下面函数使用迭代方法求最大连续子段和。对于数组{-2 , 3 , -1 , 5 , -6 , 2 },函数返回值是()。

int maxSubArray(const vector<int> &a) {
	int best = a [0];
	int current = a [0];
	for (int i = 1; i < (int)a .size(); i++) {
		current = max (a [i], current + a [i]);
		best = max (best , current);
	}
	return best ;
}
2分
登录后查看选项
15

数组a 和b 按低位在前的顺序保存两个非负大整数。下面代码实现高精度加法,横线处应填写()。

vector<int> add(const vector<int> &a , const vector<int> &b) {
	vector<int> c;
	int carry = 0 ;
	int n = max (a.size(), b.size());
	for (int i = 0 ; i < n ; i++) {
		int sum = carry;
		if (i < a.size())
			sum += a [i];
		if (i < b.size())
			sum += b [i];
		c.push_back(sum % 10);
		_____________________
	}
	if (carry)
		c.push_back(carry);
	return c;
}
2分
登录后查看选项

判断题 共10道

16

下面代码在已知结点p 的情况下,能够以的时间在单链表的p 结点之后插入新结点s 。

s->next = p->next ;
p->next = s ;
2分
登录后查看选项
17

下面代码可以安全地删除单链表的头结点,并使head 指向删除后的新头结点。

Node *p = head ;
delete p ;
head = p->next ;
2分
登录后查看选项
18

下面欧几里得算法既适用于a > b,也适用于a < b,只要a、b 是正整数。

int gcd(int a , int b) {
	while (b != 0) {
		int r = a % b ;
		a = b ;
		b = r;
	}
	return a ;
}
2分
登录后查看选项
19

下面埃氏筛从i * i 开始标记,是因为i * i 之前的i 的合数倍数已经被更小的质因子标记过。

for (int i = 2; (long long)i * i <= n ; i++) {
	if (isPrime [i]) {
		for (int j = i * i; j <= n ; j += i) {
			isPrime [j] = false ;
		}
	}
}
2分
登录后查看选项
20

下面程序的时间复杂度为O(n)。

for (int i = 1; i <= n ; i *= 2) {
	cout << i << endl;
}
2分
登录后查看选项
21

若数组a 已按升序排列,下面函数能够返回最后一个小于等于x 的元素下标;如果不存在,则返回 -1 。

int findLastLE(const vector<int> &a , int x) {
	int l = 0 , r = (int)a .size() - 1;
	int ans = -1;
	while (l <= r) {
		int mid = l + (r - l) / 2;
		if (a [mid] <= x) {
			ans = mid ;
			l = mid + 1;
		} else {
			r = mid - 1;
		}
	}
	return ans ;
}
2分
登录后查看选项
22

快速排序中如果选取区间第一个元素作为枢轴。当输入数组已经升序排列时,其最坏时间复杂度仍为 O(n log n)。

2分
登录后查看选项
23

归并排序的递推式为 T(n) = 2T(n/2) + O(n),对应的时间复杂度为 O(n log n)。

2分
登录后查看选项
24

下面的贪心代码一定能对任意硬币面值集合coins 求出money 所需的最少硬币数。

int count = 0 ;
for (int coin : coins) { // coins 按面值从大到小排列
	count += money / coin;
	money %= coin;
}
2分
登录后查看选项
25

假设两个非负高精度整数分别存储在数组a 和b 中,且。数组采用低位在前的方式存储,即 a [0] 表示个位。下面代码中的c 可以正确保存a - b 的各位数字。

int borrow = 0 ;
for (int i = 0 ; i < len ; ++i) {
	int t = a [i] - b [i] + borrow;
	if (t < 0) {
		t += 10 ;
		borrow = 1;
	} else {
		borrow = 0 ;
	}
	c [i] = t ;
}
2分
登录后查看选项

编程题 共2道

26

哥德巴赫猜想

题目描述

众所周知,哥德巴赫猜想是说,任何大于2的偶数都能写成两个质数(素数)之和。例如:

  • 4=2+2
  • 6=3+3
  • 8=3+5
  • 10=3+7=5+5

聪明的你肯定想知道,对于大于 2 的偶数 n,它有多少种写成两个质数之和的方法。例如4,6和8都只有一种方法,10有两种方法。请你编写程序计算这个问题的答案。

在本题中,我们认为两种方案不同,当且仅当两种分解方案包含的素数互不相同;即10=3+7和10=7十3是同一种方案,不能重复计数。

输入

一行,一个大于2的偶数n。

输出

一行,一个整数,表示将n写成两个质数之和的方法数。

数据范围

4≤n≤10^6

输入样例1

4

输出样例1

1

输入样例2

10

输出样例2

2

25分

C0727
登录后作答
27

饮品调制

题目描述

你想调制一份甜度恰到好处的饮品给你的朋友们品尝。

有 n 种原料可供用于调制饮品。第 i 种原料存量有 vi 升,每升含有 si 克糖分。你可以自由选择原料加入饮品,但每种原料的使用量不得超过其剩余存量。也就是说,假设第 i 种原料选用 ki 升,应当有 0≤ki≤vi,ki 可以取 0 到 vi 之间的任何数字(包括小数)。

一份甜度恰到好处的饮品需要保证甜度恰好为 t。最终你调制得到的饮品甜度将为 。为了让更多的朋友喝到饮品,请问最多能调制出多少升甜度恰到好处的饮品?如果无法调制出甜度恰到好处的饮品,则认为答案是 0。

输入

第一行,两个整数 n,t,分别表示原料种类数量,恰到好处的甜度。

接下来 n 行,每行两个整数 vi,si,分别表示第 i 种原料的存量体积,每升含有的糖分质量。

输出

一行,一个小数,表示能调制出的甜度恰到好处的饮品最大体积,保留三位小数。

数据范围

1≤n≤2000,0≤t≤200,1≤vi≤100,0≤si≤200

输入样例1

4 2

6 1

5 2

8 5

1 0

输出样例1

14.667

输入样例2

2 5

3 4

5 3

输出样例2

0.000

25分

C0728
登录后作答