2024年12月真题
一、单选题(每题2分,共30分)
正确答案:A
解析:考察函数的相关知识。函数定义、函数调用。
函数定义:
返回值类型 函数名(形参列表){
函数体
}
函数调用:
函数名(实参列表);
选项B错误:缺乏返回值类型
选项C错误:返回值类型错误
选项D错误:返回值类型错误、缺乏返回值
正确答案:B
解析:形参出现在函数定义中;实参出现在函数调用中。
选项A错误:值传递是指在调用函数时,将实际参数的值复制一份传递给函数。这种方式下,函数内部对参数的修改不会影响到实际参数。代码执行结束,times的值依然是 5。
选项C错误:n 出现在函数定义中,是形参;times 出现在函数调用中,是实参。
选项D错误:实参和形参的个数相同,类型一致。
正确答案:B
解析:& 意味着这个函数的参数传递方式是引用传递。引用传递是指在调用函数时将实际参数的地址传递到函数中,这样在函数中对参数所进行的修改,将影响到实际参数。函数func的功能是将参数翻倍。
正确答案:B
解析:第1行:c++里的动态创建数组,new运算符返回第一个元素的地址, 也就是会把数组的第一个元素的地址赋给指针p_arr。然后可以将指针当做数组的名称一样使用, 来访问数组中的元素,比如第2行,p_arr[0] = 0.2; 就是给下标为0的元素,也即第一个元素赋值为0.2。
第5行,p_arr += 1; 相当于指针p_arr的指向后移一个元素。此时从它往后数,下标为0,即第一个元素是原第二个元素,存储的值为0.5,答案选B。
其他相关知识:
1、动态创建数组相比与静态创建数组的区别是: 动态创建数组只有在需要的时候才会去真正申请内存空间。
2、当使用new分配的内存时, 应该使用delete来释放他们。
3、当使用new[]分配的内存时, 应该使用delete[]来释放他们。
4、new与delete,new[]与delete[],使用时应一一对应。例如第8行代码应该为delete[] p_arr; 对于内置数据类型,使用delete和delete[]的效果是一样的。因此delete p_arr;也正确。
正确答案:D
解析:第1行定义 int 类型变量 x,赋值为20。第2行定义 int 类型指针 p,将 x 的地址赋值给 p。*p中 “*” 为解引用运算符,可以理解为访问指针p这个地址所存储的数据。*p 和 x 表示一个意思。第3行,对*p进行操作,也就是对x进行操作,*p加2赋回给*p。代码执行完毕,x和*p值从20变成22。
正确答案:D
解析:Student 的结构体定义都没有问题。A、B、C都可以成功定义一个包含20个元素的结构体类型数组。三种方式都要掌握,尤其是C选项中的方式,虽然用的不多,但考得多。
正确答案:D
解析:第2行第2个元素和第1行第1个元素相差4个元素,一个正数32位四字节,(20)16+(4*4)10=(30)16,选D。
正确答案:D
解析:数组定义的时候同时进行赋值,也就是进行初始化,才有可能省略长度。A、B、C直接排除。选D。
且对于二维数组来说,只能省略行数,不能省略列数。
正确答案:A
解析:考察使用三个变量推出斐波那契数列的方法。选A
正确答案:C
解析:C选项错误,最好情况:当数组已经是有序的,或者只需要交换一个元素时,时间复杂度为O(n)。
正确答案:B
解析:
4 和 1 比较,交换。1, 4, 3, 1, 5, 2
4 和 3 比较,交换。1, 3, 4, 1, 5, 2
4 和 1 比较,交换。1, 3, 1, 4, 5, 2
4 和 4 比较,不交换。1, 3, 1, 4, 5, 2
5 和 2 比较,交换。1, 3, 1, 4, 2, 5
正确答案:B
解析:
n==1 要算cellRecur(1)
n==2 要算cellRecur(2)、cellRecur(1)、cellRecur(1)
n==3 要算cellRecur(3)、cellRecur(2)、cellRecur(2)、cellRecur(1)、cellRecur(1)、cellRecur(1)、cellRecur(1)
可继续往下列出,规律为
2
n
−
1
2^{n}-1
2n−1,实际上,正好是一个深度为n的满二叉树的节点个数。选B
总结点一般规律:单层循环时间复杂度为 O ( n ) O(n) O(n),双层循环嵌套时间复杂度为 O ( n 2 ) O(n^2) O(n2),类似题目中这种一拆2的递归求解时间复杂度为 O ( 2 n ) O(2^n) O(2n)
正确答案:A
解析:插入排序是一种简单直观的排序算法,其基本思想是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增加1的有序表。
本题代码:从第二个元素开始,将该元素存在base中,把base与之前的元素逐一进行比较,如果之前的元素大于base,则后移一位,直到找到一个小于等于base的元素,将base插入在该元素后边。重复此过程,直到所有元素都被插入到正确的位置。
正确答案:C
解析:考察文件重定向与文件读写操作。
A选项:freopen(“log.txt”, “w”, stdout);
freopen 函数用于重新打开一个文件,并将其与指定的流关联起来。在这里,它尝试打开名为 log.txt 的文件,使用 “w” 模式,这个模式表示以写入(覆盖原有内容)的方式打开文件。stdout 是标准输出流,在 C/C++ 中默认指向控制台,这行代码的效果就是把原本输出到控制台的内容重定向到 log.txt 文件里了,后续所有原本要打印到屏幕上的内容都会写入到这个文件中(直到重新进行流的重定向或者关闭重定向(fclose(stdout);)等操作改变这种情况)。
B选项:std::ofstream outFile(“log.txt”);
这行代码创建了一个 std::ofstream 类型(输出文件流类型)的对象 outFile,并通过构造函数指定了要关联的文件名 “log.txt”。这意味着后续可以使用 outFile 对象来向 log.txt 文件写入数据。
D选项:这段代码的核心功能是将原本输出到标准输出(通常是控制台)的内容重定向到一个名为 log.txt 的文件中,输出指定的字符串后,再将标准输出恢复到原来的状态,也就是重新让 cout 输出到控制台。
A、B两种方法至少要掌握一种,CSP复赛使用文件读写来测试数据。
正确答案:A
解析:考察异常处理。
在 C++ 中,异常处理机制通过 try、catch 语句块来实现,它提供了一种结构化的方式来处理程序运行期间出现的错误和异常情况,使得程序在遇到意外状况时能够更优雅、更健壮地做出响应,而不是直接崩溃。
A 选项:如上述代码执行分析,会进入捕获 runtime_error 类型异常的 catch 块,输出 “Caught: Runtime error occurred”,所以 A 选项正确。
B 选项:不会输出 “Caught an unknown exception”,因为已经有专门捕获 runtime_error 类型异常的 catch 块能处理抛出的异常了,不会走到捕获所有未知异常(catch(…))的块,所以 B 选项错误。
C 选项:程序不会调用 std::terminate(),因为异常被正确捕获并处理了,所以 C 选项错误。
D 选项:代码不存在编译错误,语法等方面都符合 C++ 规范,所以 D 选项错误。
二、判断题(每题2分,共20分)
正确答案:错误
解析:第1行指针的定义是正确的。但在没有给指针初始化或者赋值的情况下,不可以给 *ptr 赋值,因为此时ptr指向未知,给 *ptr 赋值会更改了未知区域的数据,造成错误。
正确答案:错误,错误,错误
解析:
第2题:错误,函数在调用之前不一定非要既声明又定义,如果定义在调用之前,可以不进行声明。如果定义在调用之后,必须进行声明。
第3题:错误,通过引用传递和指针传递时,函数内对参数的修改确实可以直接修改传入变量的值,但值传递是创建参数的副本在函数内操作,不会影响传入的原始变量。
第4题:错误。这不是一个正确的二维数组声明,数组声明时必须指定大小,当定义同时进行赋值,也就是进行了初始化时,可以省略长度,例如二维数组声明时第一维的大小可以省略,但第二维的大小必须明确指定。本题二维数组声明时未进行初始化,行数,列数都不能省略,正确形式应该是:int arr[3][4]。
正确答案:正确,正确,正确
解析:
第5题:表述正确
第6题:递归关系式法(主定理法):对于递归算法,通常会有一个递归关系式来描述算法的运行时间。比如本题T(n)=T(n-1)+n,T(0)=1。可以推出T(n)和n之间的一个关系式。如下图所示:则算法时间复杂度为
O
(
n
2
)
O(n^2)
O(n2) 。
第7题:冒泡排序平均时间复杂度和最坏情况下时间复杂度为
O
(
n
2
)
O(n^2)
O(n2) ,最优情况下(数组本身已经有序)时间复杂度为
O
(
n
)
O(n)
O(n) 。
正确答案:正确,错误
解析:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
第8题:表述正确
第9题:表述错误
正确答案:错误
解析:在 C++ 中,如果一个函数可能抛出异常,不一定非要在 try 子句里调用这个函数,只是如果不在 try 里调用且函数抛出异常没被捕获处理时,程序可能会异常终止等情况出现,比如
三、编程题(每题25分,共50分)
#include<bits/stdc++.h> //万能头文件
using namespace std;
const int N=1e6+5; //先试试,不够再加。
int a[3001];
bool vis[N];
int main() {
int n;
cin>>n;
a[1]=1;
vis[1]=true;
for(int i=2; i<=n; i++){
if(a[i-1]-i>0 && !vis[a[i-1]-i]) a[i]=a[i-1]-i;
else a[i]=a[i-1]+i;
vis[a[i]]=true;
}
sort(a+1, a+n+1); //调用排序函数排序
for(int i=1; i<=n; i++) cout<<a[i]<<" ";
return 0;
}
#include<bits/stdc++.h> //万能头文件
using namespace std;
int main() {
int t, n, flag;
string arr[100], tmp;
cin>>t;
while(t--){
cin>>n;
for(int i=0; i<n; i++) cin>>arr[i];
/*既然要求拼接后的字符串t满足:当j<i均有t_j<=t_i,i,j为字符串t的下标。
则原字符串首字母至少要满足要求,进而只有原字符串时按照字典序拼接起来才满足要求。
*/
sort(arr, arr+n); //原字符串排序
tmp="";
for(int i=0; i<n; i++) tmp+=arr[i]; //拼接
flag=1; //flag标记是否满足要求,假定满足
for(int i=1; i<tmp.size(); i++){
if(tmp[i]>=tmp[i-1]) continue;
else{ //发现不满足,置flag为0
flag=0;
break;
}
}
cout<<flag<<endl;
}
return 0;
}