2025年9月GESP编程能力认证C++等级考试五级真题(含答案和解析)_第1页
2025年9月GESP编程能力认证C++等级考试五级真题(含答案和解析)_第2页
2025年9月GESP编程能力认证C++等级考试五级真题(含答案和解析)_第3页
2025年9月GESP编程能力认证C++等级考试五级真题(含答案和解析)_第4页
2025年9月GESP编程能力认证C++等级考试五级真题(含答案和解析)_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

2025年9月GESP编程能力认证C++等级考试五级真题(含答案和解析)一、单选题(每题2分,共30分)。1.以下哪种情况使用链表比数组更合适?A.数据量固定且读多写少B.需要频繁在中间或开头插入、删除元素。C.需要高效随机访问元素D.存储空间必须连续答案:B。解析:线性表特点——内存连续,访问速度快O(1),插入删除速度慢O(n)。链表特点:内存不连续,插入/删除速度快O(1),访问速度慢O(n)。2.函数removeElements删除单链表中所有结点值等于val的结点,并返回新的头结点,其中链表头结点为head,则横线处填写()。//结点结构体。structNode{intval;Node*next;Node():val(0),next(nullptr){}Node(intx):val(x),next(nullptr){}Node(intx,Node*next):val(x),next(next){}};Node*removeElements(Node*head,intval){Nodedummy(0,head);//哑结点,统一处理头结点。Node*cur=&dummy;while(cur->next){if(cur->next->val==val){_______________________//在此填入代码。}else{cur=cur->next;}}returndummy.next;}A.Node*del=cur;cur=del->next;deletedel;B.Node*del=cur->next;cur->next=del;deletedel;C.Node*del=cur->next;cur->next=del->next;deletedel;D.Node*del=cur->next;deletedel;cur->next=del->next;答案:C。解析:需要先记录要删除的节点,然后绕过该节点,最后再释放内存。3.函数hasCycle采用Floyd快慢指针法判断一个单链表中是否存在环,链表的头节点为head,即用两个指针在链表上前进:slow每次走1步,fast每次走2步,若存在环,fast终会追上slow(相遇);若无环,fast会先到达nullptr,则横线上应填写()。structNode{intval;Node*next;Node(intx):val(x),next(nullptr){}};boolhasCycle(Node*head){if(!head||!head->next)returnfalse;Node*slow=head;Node*fast=head->next;while(fast&&fast->next){if(slow==fast)returntrue;_______________________//在此填入代码。}returnfalse;}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;答案:A。解析:根据题目文字提示,慢指针每次走1步,快指针每次走2步,所以选A。4.函数isPerfectNumber判断一个正整数是否为完全数(该数是否即等于它的真因子之和),则横线上应填写()。一个正整数n的真因子包括所有小于n的正因子,如28的真因子为1,2,4,7,14。boolisPerfectNumber(intn){if(n<=1)returnfalse;intsum=1;for(inti=2;______;i++){if(n%i==0){sum+=i;if(i!=n/i)sum+=n/i;}}returnsum==n;}A.i<=nB.i*i<=nC.i<=n/2D.i<n答案:B。解析:因数都是成对出现的,比如28的因数对1和28,2和14,4和7,所以只需要遍历到sqrt(n)就可以了。第7行判断i!=n/i是为了避免重复加平方跟。5.以下代码计算两个正整数的最大公约数(GCD),横线上应填写()。intgcd0(inta,intb){if(a<b){swap(a,b);}while(b!=0){inttemp=a%b;a=b;b=temp;}return______;}A.bB.aC.tempD.a*b答案:B。解析:欧几里得算法的核心思想是——两个整数的最大公约数等于其中较小的数和两数相除余数的最大公约数。当余数为0的时候,除数就是两个数的最大公约数。6.函数sieve实现埃拉托斯特尼筛法(埃氏筛),横线处应填入()。vector<bool>sieve(intn){vector<bool>is_prime(n+1,true);is_prime[0]=is_prime[1]=false;for(inti=2;i<=n;i++){if(is_prime[i]){for(intj=______;j<=n;j+=i){is_prime[j]=false;}}}returnis_prime;}A.iB.i+1C.i*2D.i*i答案:D。解析:埃筛的原理是从每个质数的平方开始,标记这个数字所有的倍数为合数。7.函数linearSieve实现线性筛法(欧拉筛),横线处应填入()。vector<int>linearSieve(intn){vector<bool>is_prime(n+1,true);vector<int>primes;for(inti=2;i<=n;i++){if(is_prime[i])primes.push_back(i);for(intp:primes){if(p*i>n)break;is_prime[p*i]=false;if(________)break;}}returnprimes;}A.i%p==0B.p%i==0C.i==pD.i*p==n答案:A。解析:线性筛的核心是每个合数都用自己的最小质因子标记,保证每个数字只会被标记一次,从而达到O(n)的时间复杂度。当i能被当前质数p整除时(i%p==0)说明i已经包含了p作为最小质因数,此时如果继续用更大的质数乘i进行标记,就会造成重复标记。8.关于“埃氏筛”和“线性筛”的比较,下列说法错误的是()。A.埃氏筛可能会对同一个合数进行多次标记B.线性筛的理论时间复杂度更优,所以线性筛的速度往往优于埃氏筛。C.线性筛保证每个合数只被其最小质因子筛到一次D.对于常见范围(n≤107),埃氏筛因实现简单,常数较小,其速度往往优于线性筛。答案:B。解析:线性筛的理论时间复杂度是O(n)优于埃氏筛的O(nloglogn),但在n≤107时,埃筛通常更快。9.唯一分解定理描述的是()。A.每个整数都能表示为任意素数的乘积B.每个大于1的整数能唯一分解为素数幂乘积(忽略顺序)C.合数不能分解为素数乘积D.素数只有两个因子:1和自身。答案:B。解析:唯一分解定理就是把一个合数(1既不是质数也不是合数)写成很多个质数相乘的形式,这种表示时唯一的。10.给定一个nxn的矩阵matrix,矩阵的每一行和每一列都按升序排列。函数countLE返回矩阵中第k小的元素,则两处横线上应分别填写()。//统计矩阵中<=x的元素个数:从左下角开始。intcountLE(constvector<vector<int>>&matrix,intx){intn=(int)matrix.size();inti=n-1,j=0,cnt=0;while(i>=0&&j<n){if(matrix[i][j]<=x){cnt+=i+1;++j;}else{--i;}}returncnt;}intkthSmallest(vector<vector<int>>&matrix,intk){intn=(int)matrix.size();intlo=matrix[0][0];inthi=matrix[n-1][n-1];while(lo<hi){intmid=lo+(hi-lo)/2;if(countLE(matrix,mid)>=k){________________//在此处填入代码。}else{________________//在此处填入代码。}}returnlo;}A.hi=mid-1;lo=mid+1;B.hi=mid;lo=mid;C.hi=mid;lo=mid+1;D.hi=mid+1;lo=mid;答案:C。解析:countLE(matrix,mid)的作用时统计小于等于mid的元素个数,如果count>=k,说明第k小的元素<=mid,所以答案在[lo,mid]区间,如果count<k,说明第k小的元素>mid,所以答案在[mid+1,hi]区间。11.下述C++代码实现了快速排序算法,下面说法错误的是()。intpartition(vector<int>&arr,intlow,inthigh){inti=low,j=high;intpivot=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]);returni;}voidquickSort(vector<int>&arr,intlow,inthigh){if(low>=high)return;intp=partition(arr,low,high);quickSort(arr,low,p-1);quickSort(arr,p+1,high);}A.快速排序之所以叫“快速”,是因为它在平均情况下运行速度较快,常数小、就地排序,实践中通常比归并排序更高效。B.在平均情况下,划分的递归层数为logn,每层中的总循环数为n,总时间为O(nlogn)。C.在最差情况下,每轮划分操作都将长度为的数组划分为长度为0和n-1的两个子数组,此时递归层数达到n,每层中的循环数为n,总时间为O(n2)。D.划分函数partition中“从右往左查找”与“从左往右查找”的顺序可以交换。答案:D。解析:partition函数中,两个while循环的顺序(先从右往左查找,再从左往右查找)是关键设计,确保分区正确。如果交换顺序,会导致分区错误,即pivot不能正确放置,破坏算法正确性,所以,顺序不可交换。12.下述C++代码实现了归并排序算法,则横线上应填写()。voidmerge(vector<int>&nums,intleft,intmid,intright){//左子数组区间为[left,mid],右子数组区间为[mid+1,right]。vector<int>tmp(right-left+1);inti=left,j=mid+1,k=0;while(i<=mid&&j<=right){if(nums[i]<=nums[j])tmp[k++]=nums[i++];elsetmp[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];}}voidmergeSort(vector<int>&nums,intleft,intright){if(left>=right)return;intmid=(left+right)/2;mergeSort(nums,left,mid);mergeSort(nums,mid+1,right);merge(nums,left,mid,right);}A.i<midB.j<rightC.i<=midD.j<=right答案:D。解析:根据归并排序的合并逻辑,在将左右两个有序子数组合并时,第三个while循环用于处理右子数组中剩余的元素。因此,填空的地方要确保右子数组索引j在有效范围内,也就是mid+1到right。13.假设你是一家电影院的排片经理,只有一个放映厅。你有一个电影列表movies,其中movies[i]=[start_i,end_i]表示第i部电影的开始和结束时间。请你找出最多能安排多少部不重叠的电影,则横线上应分别填写的代码为()。intmaxMovies(vector<vector<int>>&movies){if(movies.empty())return0;sort(movies.begin(),movies.end(),[](constvector<int>&a,constvector<int>&b){return______;//在此处填入代码。});intcount=1;intlastEnd=movies[0][1];for(inti=1;i<movies.size();i++){if(movies[i][0]>=lastEnd){count++;______=movies[i][1];//在此处填入代码。}}returncount;}A.a[0]<b[0]和lastEndB.a[1]<b[1]和lastEndC.a[0]<b[0]和movies[i][0]D.a[1]<b[1]和movies[i][0]答案:B。解析:第一空填写排序,按照结束时间升序排序,如果下一个电影的开始时间大于等于上一个结束时间,可以选择。14.给定一个整数数组nums,下面代码找到一个具有最大和的连续子数组,并返回该最大和。则下面说法错误的是()。intcrossSum(vector<int>&nums,intleft,intmid,intright){intleftSum=INT_MIN,rightSum=INT_MIN;intsum=0;for(inti=mid;i>=left;i--){sum+=nums[i];leftSum=max(leftSum,sum);}sum=0;for(inti=mid+1;i<=right;i++){sum+=nums[i];rightSum=max(rightSum,sum);}returnleftSum+rightSum;}inthelper(vector<int>&nums,intleft,intright){if(left==right)returnnums[left];intmid=left+(right-left)/2;intleftMax=helper(nums,left,mid);intrightMax=helper(nums,mid+1,right);intcrossMax=crossSum(nums,left,mid,right);returnmax({leftMax,rightMax,crossMax});}intmaxSubArray(vector<int>&nums){returnhelper(nums,0,nums.size()-1);}A.上述代码采用分治算法实现B.上述代码采用贪心算法C.上述代码时间复杂度为O(nlogn)D.上述代码采用递归方式实现答案:B。解析:分治思想用到递归,执行过程就是每次将问题分解为两个子问题(规模减半)并执行O(n)的合并操作,递归深度为logn,总时间复杂度为O(nlogn),这个代码未使用贪心思想。15.给定一个由非负整数组成的数组digits,表示一个非负整数的各位数字,其中最高位在数组首位,且digits不含前导0(除非是0本身)。下面代码对该整数执行+1操作,并返回结果数组,则横线上应填写()。vector<int>plusOne(vector<int>&digits){for(inti=(int)digits.size()-1;i>=0;--i){if(digits[i]<9){digits[i]+=1;returndigits;}________________//在此处填入代码。}digits.insert(digits.begin(),1);returndigits;}A.digits[i]=0;B.digits[i]=9;C.digits[i]=1;D.digits[i]=10;答案:A。解析:循环从右往前处理数字,当前位digits[i]=9时,加1后产生进位(即变为0),因此需要将当前位设为0,并继续处理前一位。如果所有位都是9,循环结束后在数组开头插入1,设为0能正确实现进位处理,其他选项不符合进位逻辑。二、判断题(每题2分,共20分)。16.基于下面定义的函数,通过判断isDivisibleBy9(n)==isDigitSumDivisibleBy9(n)代码可验算如果一个数能被9整除,则它的各位数字之和能被9整除。()。boolisDivisibleBy9(intn){returnn%9==0;}boolisDigitSumDivisibleBy9(intn){intsum=0;stringnumStr=to_string(n);for(charc:numStr){sum+=(c-'0');}returnsum%9==0;}答案:正确。解析:第一个函数判断n能否被9整除,第二个函数先将数字转换为字符串,然后再遍历每个字符,统计各个位数字之和,判断是否能被9整除。17.假设函数gcd()能正确求两个正整数的最大公约数,则下面的findMusicalPattern(4,6)函数返回2。()。voidfindMusicalPattern(intrhythm1,intrhythm2){intcommonDivisor=gcd(rhythm1,rhythm2);intpatternLength=(rhythm1*rhythm2)/commonDivisor;returnpatternLength。}答案:错误。解析:两个数的最小公倍数等于两个数的乘积除以两个数的最小公约数。18.下面递归实现的斐波那契数列的时间复杂度为O(2n)。()。longlongfib_memo(intn,longlongmemo[]){if(n<=1)returnn;if(memo[n]!=-1)returnmemo[n];memo[n]=fib_memo(n-1,memo)+fib_memo(n-2,memo);returnmemo[n];}intmain(){intn=40;longlongmemo[100];fill_n(memo,100,-1);longlongresult2=fib_memo(n,memo);return0;}答案:错误。解析:本题代码是通过记忆化搜索实现斐波那契数列,不是朴素递归。朴素递归的时间复杂度是O(2n),本题通过memo数组存储已经计算过的结果,不会重复计算,时间复杂度是O(n)。19.链表通过更改指针实现高效的结点插入与删除,但结点访问效率低、占用内存较多,且对缓存利用不友好。()。答案:正确。解析:链表的插入删除效率高O(1),访问效率低O(n)。占用的内存较多,除了数据域,还要存储指针。结点内存不连续,对缓存利用不友好。20.二分查找依赖数据的有序性,通过循环逐步缩减一半搜索区间来进行查找,且仅适用于数组或基于数组实现的数据结构。()。答案:正确。解析:二分查找需要待查找数据是有序的,且可以随机访问。21.线性筛关键是“每个合数只会被最小质因子筛到一次”,因此为O(n)。()。答案:正确。解析:线性筛法每个数字只会被标记一次。22.快速排序和归并排序都是稳定的排序算法。()。答案:错误。解析:归并排序是稳定的排序算法,快速排序是不稳定的排序算法。23.下面代码采用分治算法求解标准3柱汉诺塔问题,时间复杂度为O(nlogn)。()。voidmove(vector<int>&src,vector<int>&tar){intpan=src.back();src.pop_back();tar.push_back(pan);}voiddfs(intn,vector<int>&src,vector<int>&buf,vector<int>&tar){if(n==1){move(src,tar);return;}dfs(n-1,src,tar,buf);move(src,tar);dfs(n-1,buf,src,tar);}voidsolveHanota(vector<int>&A,vector<int>&B,vector<int>&C){intn=A.size();dfs(n,A,B,C);}答案:错误。解析:汉诺塔的递归关系为T(n)=2T(n-1)+1,时间复杂度为O(2n)。24.所有递归算法都可以转换为迭代算法。()。答案:正确。解析:递归和迭代在计算能力上是等价的,任何递归算法都可以通过使用显式的栈或队列来模拟递归调用过程,从而转换为迭代算法。25.贪心算法总能得到全局最优解。()。答案:错误。解析:贪心算法只有在满足贪心选择性质和最优子结构时才可以保证全局最优。三、编程题(每题25分,共50分)。26.试题名称:数字选取。时间限制:1.0s。内存限制:512.0MB。题目描述:给定正整数n,现在有1,2……n共计n个整数。你需要从这n个整数中选取一些整数,使得所选取的整数中任意两个不同的整数均互质(也就是说,这两个整数的最大公因数为1)。请你最大化所选取整数的数量。例如,当n=9时,可以选择1,5,7,8,9共计5个整数。可以验证不存在数量更多的选取整数的方案。输入格式:一行,一个正整数n,表示给定的正整数。输出格式:一行,一个正整数,表示所选取整数的最大数量。数据范围:对于40%的测试点,保证1≤n≤1000。对于所有测试点,保证1≤n≤105。参考程序。#include<algorithm>#include<cstdio>usingnamespacestd;constintN=1e5+5;intn,p[N],cnt;boolnp[N];intmain(){scanf("%d",&n);for(inti=2;i<=n;i++){if(!np[i])p[++cnt]=i;for(intj=1;j<=cnt&&i*p[j]<=n;j++){np[i*p[j]]=1;if(i%p[j]==0

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论