样题 GESP等级认证C++编程(五级)试题解析

【单选题】(每题2分)

1、以下不属于计算机输出设备的有?( )

A、麦克风    B、音箱    C、打印机    D、显示器   

正确答案:A

试题解析:麦克风是属于计算机的输入设备。

2、小明想了一个 1~100 之间的整数。你可以做多次猜测,每次猜测之后,如果你没有猜中,小明会告诉你,你猜的数比他想的数大还是小。你希望你在运气最坏的情况下花费最少的次数猜中,请问你运气最坏的情况下会猜( )次?(包括最后猜中的那次)

A、5    B、6    C、7    D、100    

正确答案:C

试题解析:根据二分查找算法的思想,为了在运气最坏的情况下最少次数猜中,我们可以每次将搜索范围缩小一半。

对于N个数字,最多的猜测次数则是LogN。

本例中,因为2的6次方是64,而2的7次方128,所以最多需要7次可以猜中。

3、关于分治算法,下列说法错误的是?( )

A、分治算法的核心思想是分而治之,即把问题转化为多个规模更小的子问题求解。    B、分治算法可以不使用递归实现。   

C、分治算法的时间复杂度是 O(logN),其中 N 表示问题的规模。    D、分治算法通常较容易在多核处理器上实现加速。   

正确答案:C

试题解析:选项A是分治算法的核心思想,是正确的。

选项B,虽然分治算法经常用递归来实现,但也可以使用迭代或循环等方式实现。

选项C,分治算法的时间复杂度通常是 O(n log n) 或者 O(n^2),这取决于具体的问题和算法设计。只有在对半分割的情况下,时间复杂度才是 O(logN)。

选项D,因为分治算法可以将问题分解为多个子问题,并行处理这些子问题,可以在多核处理器上实现加速。

4、有关下面C++代码说法错误的是?( )

#include <iostream>

using namespace std;

int factA(int n) {

    if (n <= 1)

        return 1;

    int ret = 1;

    for (int i = 2; i <= n; ++i)

        ret *= i;

    return ret;

}

int factB(int n) {

    return n == 1 ? 1 : n * factB(n - 1);

}

int main() {

    int n;

    cin >> n;

    cout << factA(n)<<' '<< factB(n) << endl;

    return 0;

}

A、factA()采用循环方式求n的阶乘,factB()采用递归方式求n的阶乘   

B、程序执行时如果输入5,能实现求其阶乘,程序输出结果为120 120    C、任何递归程序都可以使用循环改写   

D、程序执行时如果输入100,不能正确求出100的阶乘   

正确答案:C

试题解析:理论上所有递归都可以用循环解决,但是大量的递归用循环实现代码复杂度较大,且易出错。

程序执行时如果输入100,结果超过int类型的表示范围,不能正确求出100的阶乘。

5、下面C++代码意在实现字符串反序的功能。关于这段代码,以下说法正确的是?( )

#include <iostream>

#include <cstring>

using namespace std;

void printSReverse(char *sIn, int len) {

    if (len <= 1) {

        cout << sIn[0];

    } else {

        cout << sIn[0];

        printSReverse(sIn + 1, len - 1);

    }

}

int main() {

    char sIn[100] = "Hello";

    printSReverse(sIn, strlen(sIn));

    return 0;

}

A、这段代码可以正确实现字符串反序的功能,其输出为olleH   

B、这段代码不能正确实现字符串反序的功能,其输出为Hello   

C、这段代码不能正确实现字符串反序的功能,其输出为HHHHH   

D、这段代码不能正确实现字符串反序的功能,其输出为ooooo   

正确答案:B

试题解析:这段程序不能正确实现字符串反序,原因在于printSReverse()函数中的else部分程序是先打印sIn[0],再进行递归调用;

把cout<<sIn[0];这句移到printSReverse(sIn + 1, len - 1);则可以正确对字符串反序,这样递归函数返回的时候会依次打印反序的字符。

6、阅读下面C++实现的二分查找代码,下列说法中错误的是?( )

int binarySearch(int *arr, int l, int r, int x) {

    if (r >= l) {

        int mid = l + (r - l) / 2;

        if (arr[mid] == x)

            return mid;

        else if (arr[mid] > x)

            return binarySearch(arr, l, mid - 1, x);

        else

            return binarySearch(arr, mid + 1, r, x);

    } else

        return -1;

}

A、上面代码实现的二分查找,最少只需查找一次即可得到结果。   

B、如果调用该函数在列表{2, 3, 4, 10, 12}中查找元素0,则它实际被调用3次。   

C、如果调用该函数在列表{2, 3, 4, 10, 12}中查找元素3,则它实际被调用3次。   

D、如果调用该函数在列表{2, 3, 4, 10, 12}中查找元素10,则它实际被调用3次。   

正确答案:D

试题解析:选项D是错的。

因为binarySearch()中的l,r指的是数组的起始和终止下标,对于数组{2, 3, 4, 10, 12},查找元素10时:

第一次调用binarySearch时,mid=2,arr[mid]=4,比10小,继续第二次调用binarySearch(arr, 3, 4, 10),mid = l + (r - l) / 2=3,arr[mid]的值为10,已经找到元素10,返回mid;

所以实际上它被调用了2次。

7、使用如下代码片段定义四个字符串(假设头文件已正确定义),以下说法错误的是?( )

string str1 = "abc";

string str2 = str1;

char str3[] = "abc";

char *str4  = str3;

A、对于四个字符串,都可以使用std::cout输出其中的内容(例如,cout << str3;)。   

B、str3只占用4字节内存,但str1却要占用更多内存。   

C、由于str2由str1直接赋值得到,因此二者指向同一块内存,即修改str1的内容后str2的内容也会随之改变。   

D、由于str4由str3直接赋值得到,因此二者指向同一块内存,即修改str3的内容后str4的内容也会随之改变。   

正确答案:C

试题解析:C++ 中的 string 是一个标准库类型,它被设计用来方便地处理字符串。它实际上是一种动态数组,可以自动管理其内存。

使用string str2 = str1;将为str2重新分配内存,和str1存储内存不同,所以修改str1的内容不会影响str2。

8、有关下面C++代码正确的是?( )

#include <iostream>

using namespace std;

void f1() {

    cout <<"f1()" << endl;

}

void f1(int x) {

    cout << "f1("<< x <<")" << endl;

}

int main() {

    f1();

    f1(0);

    f1('0');

    return 0;

}

A、该程序不能正常运行,因为f1函数被重复定义。    B、该程序可以正常运行,输出结果共3行,依次为 f1()、f1()、f1()。   

C、该程序可以正常运行,输出结果共3行,依次为 f1()、f1(0)、f1(0)。   

D、该程序可以正常运行,输出结果共3行,依次为 f1()、f1(0)、f1(48)。   

正确答案:D

试题解析:函数f1被重载了两次:一次没有参数,另一次带一个int类型的参数。

调用f1();打印的是“f1()”;

调用f1(0);打印的则是“f1(0)”;

调用f1('0');打印的是'0'的ASCII码,“f1(48)”;

9、关于C++程序的异常处理,以下选项中描述错误的是?( )

A、编程语言中的异常和错误是不同的概念。    B、异常一旦发生,程序便一定不能继续执行。   

C、通过try、catch等保留字提供异常处理功能。    D、程序使用throw在任何地方抛出各种异常。  

正确答案:B

试题解析:选项B的说法错误;

C++ 中的异常处理机制允许程序捕获和处理异常,从而使程序能够在异常发生后继续执行或采取适当的措施。

10、下面代码执行后的输出是?( )

#include <iostream>

using namespace std;

int fibonacci(int N) {

    cout << N << ",";

    if (N == 1 || N == 2) {

        return 1;

    } else {

        return fibonacci(N - 1) + fibonacci(N - 2);

    }

}

int main() {

    cout << fibonacci(5) << endl;

    return 0;

}

A、5,4,3,2,1,2,1,5    B、5,4,3,2,1,2,3,2,1,5    C、5,4,4,3,2,1,3,2,1,5    D、5,4,3,2,1,3,2,1,5   

正确答案:B

试题解析:调用 fibonacci(5):

    进入 fibonacci(5),输出 5,;

    调用 fibonacci(4):

        进入 fibonacci(4),输出 4,;

        调用 fibonacci(3):

            进入 fibonacci(3),输出 3,;

            调用 fibonacci(2):

                进入 fibonacci(2),输出 2,;

                返回 1;

            调用 fibonacci(1):

                进入 fibonacci(1),输出 1,;

                返回 1;

            返回 fibonacci(2) + fibonacci(1),即 2;

        调用 fibonacci(2):

            进入 fibonacci(2),输出 2,;

            返回 1;

        返回 fibonacci(3 - 1) + fibonacci(3 - 2),即 3;

    调用 fibonacci(3):

        进入 fibonacci(3),输出 3,;

        调用 fibonacci(2):

            进入 fibonacci(2),输出 2,;

            返回 1;

        调用 fibonacci(1):

            进入 fibonacci(1),输出 1,;

            返回 1;

        返回 fibonacci(2) + fibonacci(1),即 2;

    返回 fibonacci(4 - 1) + fibonacci(4 - 2),即 5;

最终输出为:5,4,3,2,1,2,3,2,1,5。

11、下列代码中,函数f的作用是?( )

int f(int a, int b) {

    return b == 0 ? a : f(b, a % b);

}

A、求a和b的最大公共质因子    B、求a和b的最小公共质因子    C、求a和b的最大公约数    D、求a和b的最小公倍数   

正确答案:C

试题解析:f函数接受两个参数a和b,如果b为0,则返回a。

如果b不为0,那么函数会递归地调用自身,将b和a对b的余数(即a % b)作为新的参数,直到b为0为止。

因此,这个函数最终会返回a和b的最大公约数。所以正确答案是C、求a和b的最大公约数。

12、下面C++代码用于排序,下列说法中错误的是?( )

void sortA(int *arr, int n) {

    for (int i = 0; i < n; ++i)

        for (int j = 0; j < n - i - 1; ++j)

            if (arr[j] > arr[j + 1]) {

                int tmp = arr[j];

                arr[j] = arr[j + 1];

                arr[j + 1] = tmp;

            }

}

void sortB(int *arr, int start, int end) {

    if (start >= end)

        return;

    int middle = (start + end) / 2;

    sortB(arr, start, middle);

    sortB(arr, middle + 1, end);

    int leftSize = middle - start + 1;

    int rightSize = end - middle;

    int *left = new int[leftSize];

    int *right = new int[rightSize];

    for (int i = 0; i < leftSize; i++)

        left[i] = arr[start + i];

    for (int j = 0; j < rightSize; j++)

        right[j] = arr[middle + 1 + j];

    int i = 0;

    int j = 0;

    int k = start;

    while (i < leftSize && j < rightSize) {

        if (left[i] <= right[j]) {

            arr[k] = left[i];

            i++;

        } else {

            arr[k] = right[j];

            j++;

        }

        k++;

    }

    while (i < leftSize) {

        arr[k] = left[i];

        i++;

        k++;

    }

    while (j < rightSize) {

        arr[k] = right[j];

        j++;

        k++;

    }

    delete[] left;

    delete[] right;

}

A、两种排序算法的时间复杂度不同。    B、两种排序算法的空间复杂度一致。   

C、sortA的时间复杂度在最好和最坏情况下都是。   

D、sortB的平均时间复杂度、最好情况的时间复杂度都是 O(logN),最坏情况的时间复杂度是。   

正确答案:D

试题解析:sortA 函数使用的是冒泡排序(Bubble Sort)算法,sortB 函数使用的是归并排序(Merge Sort)算法。

冒泡排序的时间复杂度与输入数据的初始状态有关,最好情况下的时间复杂度是 O(N),即输入数据已经是有序的情况下,只需要遍历一次数据即可完成排序。最坏情况下的时间复杂度是 O(N^2)。

归并排序的时间复杂度与输入数据的规模有关,平均时间复杂度、最好情况的时间复杂度和最坏情况的时间复杂度都是 O(NlogN)。

13、上一题中的sortB函数,明显体现出的算法思想和编程方法包括?( )

A、递归    B、分治    C、A、B都正确    D、A、B都不正确   

正确答案:C

试题解析:在给定的sortB函数中,我们可以看到明显的递归和分治思想和编程方法的体现。

所以选择答案C。

14、下列哪个算法并没有体现分治思想?( )

A、二分查找。    B、埃氏筛法。    C、归并排序。    D、快速排序。   

正确答案:B

试题解析:没有体现分治思想的是埃氏筛法(二分查找体现了分治思想;C和D都是排序,也体现了分治思想)。

因为埃氏筛法是一种简单的筛选法,它的基本思想是从2开始,逐步筛选出所有合数,直到只剩下素数为止。它并没有将问题分解为更小的子问题,然后再合并这些子问题的解以得到原问题的解。与此相反,它通过逐步筛选来解决问题。

15、下列关于链表说法,正确的是?( )

A、不能用数组来实现链表。    B、在链表头部插入元素的时间复杂度是 O(1)。   

C、循环链表使得任意一个结点都可以很方便地访问其前驱与后继。   

D、从双向链表的任意一个节点出发,并不一定能够访问到所有其他节点。   

正确答案:B

试题解析:当在链表头部插入一个新节点时,只需要移动一次指针,这个操作只需要常数时间就能完成,因此时间复杂度为 O(1)。

事实上,我们可以使用数组来模拟实现链表的基本功能。

循环链表并不会自动提供访问每个节点的前驱和后继的便利性。

双向链表的特点是每个节点既有指向下一个节点的指针,也有指向前一个节点的指针,因此从任意一个节点出发,都可以遍历访问到所有其他节点。

【判断题】(每题2分)

16、计算机硬件主要包括运算器、控制器、存储器、输入设备和输出设备。( )

正确答案:正确

试题解析:该说法正确。计算机硬件主要包括运算器、控制器、存储器、输入设备和输出设备。

17、唯一分解定理指的是分解质因数只有唯一的一种算法。( )

正确答案:错误

试题解析:唯一分解定理指的是每个大于1的自然数都可以唯一地分解为质数的乘积,而不是指分解质因数只有唯一的一种算法。因此,该说法是不正确的。

18、埃氏筛法用于找出自然数N以内的所有质数,其时间复杂度为,因为判定一个数是否为质数的时间复杂度为 O(N)。( )

正确答案:错误

试题解析:埃氏筛法是一种用于求解素数的算法。它通过逐步筛掉合数来得到素数。

埃氏筛法的时间复杂度为O(nlog(log(n)))。

19、贪心法的每一步都采取局部最优策略,因此必然能实现全局最优。( )

正确答案:错误

试题解析:该说法不一定正确。

贪心算法通过每一步选择局部最优解来构建全局最优解,但并不能保证每一步都能得到最优解,因为可能存在某些情况,使得在当时看来的局部最优解却不能导致全局最优解。

20、在C++语言中,函数的参数也可以是另一个函数。( )

正确答案:正确

试题解析:在C++语言中,函数可以有另一个函数作为它的参数,这是一种函数指针作为函数参数的使用方式。

21、在C++语言中,内置的排序算法(algorithm库中的sort函数)只能对C++的基础类型(如 int、double 等)做排序,而不能对自定义类型做排序。( )

正确答案:错误

试题解析:该说法不正确。

在C++语言中,内置的排序算法(如algorithm库中的sort函数)可以应用于自定义类型,而不仅限于基础类型。这是通过重载比较运算符(<、>、<=、>=)来实现的。

22、在任何场景下,链表都是比数组更优秀的数据结构。( )

正确答案:错误

试题解析:该说法不正确。

链表和数组都是常见的数据结构,它们都有自己的优缺点,适用于不同的场景。

23、在C++语言中,可以使用delete来释放指针指向的内存空间。( )

正确答案:正确

试题解析:该说法是正确的。

在 C++ 中,使用 new 运算符可以动态地分配内存空间,返回的是指向新分配的内存空间的指针。

为了避免内存泄漏,需要在不需要使用这些内存空间时手动释放它们。可以使用 delete 运算符来释放一个指针指向的动态分配的内存空间。

24、选择排序和快速排序都是不稳定的。( )

正确答案:正确

试题解析:该说法正确。选择排序和快速排序都是不稳定的排序算法。

25、二分查找法可以应用于有序序列(如升序排序的整数数组),也可以应用于无序序列(如乱序的整数数组)。

正确答案:错误

试题解析:该说法不正确。

二分查找法只能应用于有序序列,如果使用二分查找法在无序序列中搜索元素,可能会得到错误的结果。

【编程题】

26、小杨的锻炼问题

【问题描述】

小杨的班级里共有 N 名同学,每位同学都有各自的锻炼习惯。具体来说,第 i 位同学每隔 ai 天就会进行一次锻炼(也就是说,每次锻炼会在上一次锻炼的 ai 天后进行)。

某一天,班上的 N 名同学恰好都来进行了锻炼。他们对此兴奋不已,想要计算出下一次所有同学都来锻炼,至少要过多少天。但他们不会计算,你能帮帮他们吗?

【输入描述】

第一行一个整数 N,表示同学的数量。

第二行 N 个用空格隔开的正整数,依次为 a0,a1,…,aN?1。

【输出描述】

输出一个整数,表示下一次所有同学都来锻炼,至少要过多少天。

【特别提醒】

在常规程序中,输入、输出时提供提示是好习惯。但在本场考试中,由于系统限定,请不要在输入、输出中附带任何提示信息。

【样例输入1】

3

1 2 3

【样例输出1】

6

【样例解释1】

第一位同学每天都锻炼;第二位同学每 2 天锻炼一次;第三位同学每 3 天锻炼一次。因此,6 天之后,三位同学都会进行锻炼。在此之前,第二位同学只会在第 2,4 天进行锻炼,第三位同学只会在第 3 天进行锻炼,他们都无法相遇。

【样例输入2】

4

2 4 8 16

【样例输出2】

16

【样例解释2】

第四位同学每 16 天锻炼一次,而第 16 天后也恰好是前三位同学锻炼的日子。

【样例输入3】

4

2 4 6 8

【样例输出3】

24

【数据规模】

对于 20 的测试点,保证 N = 2。

对于 50 的测试点,保证 N ≤ 4。

对于所有测试点,保证 2 ≤ N ≤ 10,1 ≤ ai ≤ 50。

【参考程序】

#include <iostream>

using namespace std;

unsigned long long gcd(unsigned long long a, unsigned long long b) {

    if (a > b) swap(a, b);

    while (a % b) {

        unsigned long long t = a % b;

        a = b;

        b = t;

    }

    return b;

}

//此题要点找到最小公倍数

int main() {

    int N;

    cin >> N;

    unsigned long long lcm;

    cin >> lcm;

    for (int i = 1; i < N; i++) {

        unsigned long long t;

        cin >> t;

        unsigned long long g = gcd(lcm, t); // 找到两数的最大公约数

        lcm = lcm * t / g; // 找到两数的最小公倍数

    }

    cout << lcm;

}

27、小杨的列队问题

【问题描述】

小杨的班级里共有 N 名同学,学号从 0 至 N - 1。

某节课上,老师要求同学们进行列队。具体来说,老师会依次点名 M 名同学,让他们加入队伍。每名新入队的同学需要先站到队伍末尾(刚开始队伍里一个人都没有,所以第一个入队的同学只需要站好即可),随后,整个队伍中的所有同学需要按身高从低到高重新排序(身高相同的同学之间的顺序任意)。

排队很容易,但重新排序难倒了同学们。稍加讨论后,他们发现可以通过交换位置的方法来实现排序。具体来说,他们可以让队伍中的两名同学交换位置,这样整个队伍的顺序就会发生变化,多经过这样的几次交换后,队伍的顺序就可以排好。

例如:队伍中有 4 名同学,学号依次为 10、17、3、25,我们可以令 3 号同学和 10 号同学交换位置,则交换后的队伍顺序变为 3、17、10、25,这就是一次交换位置。

聪明的小杨想要知道:在老师每次点名一位新同学加入队伍后,在原有队伍的基础上,同学们最少要进行几次交换位置,才能完成老师按身高排序的要求。

【输入描述】

第一行一个整数 N,表示同学的数量。

第二行 N 个用空格隔开的正整数,依次表示学号为 0、1、…、N - 1 的同学的身高(不超过 2,147,483,647)。

第三行一个整数 M,表示老师点名的数量。

接下来 M 行,依次描述 M 次点名:每行一个整数 x(0≤x<N),表示要求学号为 x 的同学加入队伍。保证该名同学此前不在队伍中。

对于所有的测试点,保证 1≤M≤N≤2,000。对于 50 的测试点,保证所有同学的身高互不相同。

【输出描述】

输出 M 行,依次表示对于每次点名,同学们最少要进行几次交换位置,才能完成按身高排序的要求。

【特别提醒】

在常规程序中,输入、输出时提供提示是好习惯。但在本场考试中,由于系统限定,请不要在输入、输出中附带任何提示信息。

【样例输入1】

5

170 165 168 160 175

4

0

3

2

1

【样例输出1】

0

1

1

2

【样例解释1】

初始时队伍为空,身高为 170 的 0 号同学加入队伍,不需要任何交换位置。

接着,身高为 160 的 3 号同学加入队伍的末尾,此时两位同学需要进行依次交换位置,才能保证身高更矮的 3 号同学排在身高更高的 0 号同学前面。

接着,身高为 168 的 2 号同学加入队伍的末尾,此时队伍中的同学学号(身高)依次为 3(160)、0(170)、2(168),此时 2 号同学可以和 0 号同学进行一次交换位置,即可完成排序要求。

接着,身高为 165 的 1 号同学加入队伍的末尾,此时队伍中的同学学号(身高)依次为 3(160)、2(168)、0(170)、1(165),此时可以令 1 号同学和 2 号同学进行一次交换位置,使队伍变为 3(160)、1(165)、0(170)、2(168);随后再令 0 号同学和 2 号同学进行一次交换位置,使队伍变为 3(160)、1(165)、2(168)、0(170),即可完成排序要求。

【样例输入2】

4

20 20 20 10

4

0

1

2

3

【样例输出2】

0

0

0

1

【样例解释2】

前三位加入队伍的同学(0、1、2 号同学)身高都相同,不需要进行任何交换位置。最后加入队伍的 3 号同学身高最矮,需要和队头的 0 号同学交换位置,方可完成排序要求。

【参考程序】

#include <iostream>

#include <vector>

using namespace std;

int main() {

    uint64_t N, M;

    cin >> N; // 总共N个同学

    uint64_t a[N];

    for (uint64_t i = 0; i < N; i++) cin >> a[i]; // 输入所有身高

    cin >> M; // 输入需要排队的人数

    uint64_t b[M] = {0}; // 定义新的排队队列

    uint64_t ct[M] = {0};

    for (uint64_t i = 0; i < M; i++) { // 排队

        uint64_t t;

        cin >> t;

        b[i] = a[t]; // 排入队尾

        ct[i] = 0; // 交换位置的次数

        for (uint64_t j = 0; j < i; j++) {

            if (b[j] > b[i]) {

                swap(b[j], b[i]);

                ct[i]++;

            }

        }       

    }

    for (uint64_t i = 0; i < M; i++) {

    cout << ct[i] << endl;

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程小伙伴测评网

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值