视频讲解:GESP2025年9月五级C++真题讲解
一、单选题
第1题

解析:
答案B,链表的插入删除操作更合适,数组的随机访问更合适
第2题

解析:
答案C,
cpp
//保持cur的next
Node* del = cur->next;
//cur的next 指向下下个
cur->next = del->next;
//删除原来cur的next
delete del;
第3题

解析:
答案A,
cpp
slow走1步
slow = slow->next
fast走2步
fast = fast->next->next
第4题

解析:
答案B,
cpp
sum+=i; //累加当前因数
if(i != n/i) sum+=n/i; //累加对应的大因数
循环所有小因数即可
例如28有因数1 2 4 7 14
循环2至根号28,即 2 3 4 5 ,只有 2、4为因数,累加2 4 和对应的大因数 14 7
第5题

解析:
答案B,
cpp
当除数b为0时,被除数a为最大公约数,例如:
a/b
9/6=1......3
6/3=2......0
3/0
第6题

解析:
答案C,标记i的所有倍数为不是质数,从i的平方开始,即i*i,之前小的倍数都被更小的质数标记了
cpp
例如如下
i:2时
数字:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15....
标记:0 0 0 1 0 1 0 1 0 1 0 1 0 1 0
i:3时,从9开始即可,3的两倍被i为2标记过了
数字:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15....
标记:0 0 0 1 0 1 0 1 1 1 0 1 1 1 1
第7题

解析:
答案A,线性筛,通过最小的质因数去标记,一旦发现i是质数p的因数,就可以停止标记了
cpp
例如
i为2时,质数有:2。标记2*2=4
数字:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15...
下标:0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
i为3时,质数有:2,3。标记3*2=6,3*3=9
数字:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15...
下标:0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0
i为4时,质数有:2,3。标记4*2=8
因为4%2==0,4*3=12没必要标记,12会被6*2标记
数字:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15...
下标:0 0 0 1 0 1 0 1 1 0 0 0 0 0 0 0
第8题

解析:
答案B,只求素数,埃筛更快,最小质因子 / 欧拉函数 / 莫比乌斯函数时用线筛才更好
cpp
bool isp[10000001];
vector<int> primes;
void sieve(int n){
for(int i=2;i<=n;i++) isp[i]=1;
for(int i=2;i<=n/i;i++) //只求素数,埃筛可大大缩小范围
if(isp[i])
for(int j=i*i;j<=n;j+=i) isp[j]=0;
for(int i=2;i<=n;i++) if(isp[i]) primes.push_back(i);
}
int minp[10000001];
vector<int> primes;
void linsieve(int n){
for(int i=2;i<=n;i++){ //线筛只能老老实实全部循环
if(!minp[i]) minp[i]=i, primes.push_back(i);
for(int p: primes){
if(p>minp[i] || 1LL*i*p>n) break;
minp[i*p]=p;
}
}
}
第9题

解析:
答案B,例如12能分解成的质因数2*2*3,不考虑顺序,只有一种
第10题

解析:
答案C,
cpp
if( countLE(matrix,mid) >= k ){ //中间值>=k
hi=mid;//保留这一行
}else{// 中间值<k
lo=mid+1//往更大去找
}
第11题

解析:
答案D,基准元素最后要和i做交换,所以i要保持是小的那一边,所以得先移动j
cpp
最初
i
4 2 8 6 1 8 9
j
第1次:先移动i,在移动j
i
4 2 8 6 1 8 9
j
交换后:
i
4 2 1 6 8 8 9
j
第2次:先移动i,在移动j
i
4 2 1 6 8 8 9
j
交换后:6 4交换快速排序错误
i
6 2 1 4 8 8 9
j
第12题

解析:
答案D,由第4行可知,j的尽头在right,这里要循环剩余的所以j元素,所有要循环到j的尽头,即j<=right
第13题

解析:
答案B,贪心算法,哪个电影最早结束,排哪个在前面,即a1<b1,1代表结束时间,排完这个电影,需要更新结束时间,即lastEnd = moviesi1;
第14题

解析:
答案B,用分治实现,不是贪心
第15题

解析:
答案A,digitsi=9,9+1进位了,所以digitsi=0
二、判断题
第1题

解析:
答案√,两个函数的功能符合预期,在isDivisibleBy9是true的情况下,isDivisibleBy9(n) == isDigitSumDivisibleBy9(n)能够正确判断
//函数判断 能否被9整除
bool isDivisibleBy9(int n) {
return n % 9 == 0;
}
//函数计算各个位数之和能否被9整除
bool isDigitSumDivisibleBy9(int n) {
int sum = 0;
string numStr = to_string(n);//转为字符串
for (char c : numStr) {//循环字符串
sum += (c - '0');//转为int 进行累加
}
return sum % 9 == 0;
}
第2题

解析:
答案×,gcd(hm1,hm2)=2 ,(hm1*hm2)/com=(6*2)/2=6
第3题

解析:
答案×,当斐波那契数出现过,函数不会递归了,时间复杂度是O(n)
第4题

解析:
答案√,
链表插入删除,通过改前驱和后驱结点,O(1)就能完成
链表的结点访问,没有下标,只能遍历整个链表查找,效率低
链表的结点存储,需要存储数据+指针,占用内存多
链表存储在随机位置,CPU访问时回同时访问附近的数据,存入缓存,导致缓存利用不友好
第5题

解析:
答案√,二分查找的前提是数组有序,每次需要获取正中间,需要依赖数组的下标实现,不可以用链表
第6题

解析:
答案√,线性筛的时间复杂度是O(n),埃氏筛的时间复杂度是O(nloglogn)
第7题

解析:
答案×,只有选择、快速、希尔、堆排序不稳定
第8题

解析:
答案×,dfs函数每次再调用2次dfs,时间复杂度是O(2^n)
第9题

解析:
答案√,任何递归可以改成while,任何while可以改成for
//递归计算阶乘
int f(int n){
if(n<=1) return 1;
return n*f(n-1);
}
//递归改成while
int n=5,ans=1;
while(n>1){
ans*=n--;
}
//while改成for
int ans=1;
for(int n=5;n>1;n--) ans*=n;
第10题

解析:
答案×,
例如1/3/4 面值硬币凑6元(可能少的硬盘)
贪心第1个硬币用4,之后只能4 1 1凑出6
真正全局最优解是 3 3凑出6
三、编程题
第1题 GESP202509 五级 数字选取
题目描述
给定正整数 n,现在有 1,2,...,n 共计 n 个整数。你需要从这 n 个整数中选取一些整数,使得所选取的整数中任意两个不同的整数均互质(也就是说,这两个整数的最大公因数为 1)。请你最大化所选取整数的数量。
例如,当 n=9 时,可以选择 1,5,7,8,9 共计 5 个整数。可以验证不存在数量更多的选取整数的方案。
输入格式
一行,一个正整数 n,表示给定的正整数。
输出格式
一行,一个正整数,表示所选取整数的最大数量。
输入输出样例
输入 #1
6
输出 #1
4
输入 #2
9
输出 #2
5
说明/提示
对于 40% 的测试点,保证 1≤n≤1000。
对于所有测试点,保证 1≤n≤10^5。
答案
cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
//1)确定范围n
int n;cin>>n;
//2)埃筛2至n
int ans=1;//包括1
//初始化所有为false,假设所有都是质数
bool flag[100010]={};
for(int i=2;i<=n;i++){
//是质数,将所有倍数标记为不是质数
if(flag[i]==false){
for(int j=2*i;j<=n;j+=i){
flag[j]=true;
}
//3)是质数 ,+1
ans++;
}
}
cout<<ans;
}
第2题 GESP202509 五级 有趣的数字和
题目描述
如果一个正整数的二进制表示包含奇数个 1,那么小 A 就会认为这个正整数是有趣的。
例如,7 的二进制表示为 (111)2,包含 1 的个数为 3 个,所以 7 是有趣的。但是 9=(1001)2 包含 2 个 1,所以 9 不是有趣的。
给定正整数 l,r,请你统计满足 l≤n≤r 的有趣的整数 n 之和。
输入格式
一行,两个正整数 l,r,表示给定的正整数。
输出格式
一行,一个正整数,表示 l,r 之间有趣的整数之和。
输入输出样例
输入 #1
cpp
3 8
输出 #1
cpp
19
输入 #2
cpp
65 36248
输出 #2
cpp
328505490
说明/提示
【数据范围】
对于 40% 的测试点,保证 1≤l≤r≤10^4。
对于另外 30% 的测试点,保证 l=1 并且 r=2k−1,其中 k 是大于 1 的正整数。
对于所有测试点,保证 1≤l≤r≤10^9。
【提示】
由于本题的数据范围较大,整数类型请使用 long long。
答案
cpp
#include<bits/stdc++.h>
using namespace std;
long long cal(int x){//65
//计算出周期0-63
long long end= (x+1)-(x+1)%4-1;
// 0至63周期和
long long ans=(0+end)*(end+1)/4;
//特殊处理 超出的64 65
for(long long i=end+1;i<=x;i++){
int count=0;
int temp=i;
while(temp){
if(temp&1) count++;
temp>>=1;
}
if(count%2==1) ans+=i;
}
//返回结果
return ans;
}
int main(){
int L,R;
cin>>L>>R;
cout<<cal(R)-cal(L-1);
}