2020年12月 C/C++(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

2020年12月 C/C++(二级)真题解析#中国电子学会#全国青少年软件编程等级考试_第1张图片

C/C++编程(1~8级)全部真题・点这里

第1题:数组指定部分逆序重放

将一个数组中的前k项按逆序重新存放。例如,将数组8,6,5,4,1前3项逆序重放得到5,6,8,4,1。
时间限制:1000
内存限制:65536
输入
输入为两行: 第一行两个整数,以空格分隔,分别为数组元素的个数n(1 < n < 100)以及指定的k(1 <= k <= n)。 第二行是n个整数,每两个整数之间用空格分隔。
输出
输出为一行:输出按题目要求逆序后数组的整数,每两个整数之间用空格分隔。
样例输入
5 3
8 6 5 4 1
样例输出
5 6 8 4 1

要解决这个问题,我们可以使用数组的逆序操作来实现指定部分的逆序重放。以下是解决该问题的示例代码:

#include 

void reverseArray(int arr[], int start, int end) {
    while (start < end) {
        int temp = arr[start];
        arr[start] = arr[end];
        arr[end] = temp;
        start++;
        end--;
    }
}

int main() {
    int n, k;
    scanf("%d %d", &n, &k);

    int arr[100];

    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }

    reverseArray(arr, 0, k - 1);
    reverseArray(arr, k, n - 1);
    reverseArray(arr, 0, n - 1);

    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

在程序中,我们首先定义了一个reverseArray函数,它用于将数组中指定范围内的元素进行逆序操作。函数接受一个整数数组arr,以及指定的开始位置start和结束位置end

reverseArray函数中,我们使用双指针的方法,将开始位置和结束位置的元素进行交换,然后逐步向中间移动指针,继续进行交换,直到两个指针相遇。这样就完成了指定范围内的逆序操作。

在主函数中,我们首先使用scanf函数读取输入的数组元素个数n和指定的k。然后,我们声明一个大小为100的整数数组arr来存储输入的数组元素。

接下来,我们使用一个循环来读取输入的数组元素,并将其存储到数组arr中。

然后,我们依次调用reverseArray函数进行三次逆序操作。首先,我们将数组的前k项进行逆序操作;接着,我们将剩余部分(即从第k项到最后一项)进行逆序操作;最后,我们再次对整个数组进行逆序操作,即可得到按题目要求逆序后的数组。

最后,我们使用一个循环遍历数组arr,并使用printf函数按要求输出数组的元素。

你可以将以上代码保存为一个.c文件,使用C语言编译器进行编译和运行。然后,按照输入要求输入数组的元素个数、指定的k和具体的数组元素,即可得到按题目要求逆序后的数组。

第2题:简单密码

Julius Caesar曾经使用过一种很简单的密码。对于明文中的每个字符,将它用它字母表中后5位对应的字符来代替,这样就得到了密文。比如字符A用F来代替。如下是密文和明文中字符的对应关系。 密文 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 明文 V W X Y Z A B C D E F G H I J K L M N O P Q R S T U 你的任务是对给定的密文进行解密得到明文。 你需要注意的是,密文中出现的字母都是大写字母。密文中也包括非字母的字符,对这些字符不用进行解码。
时间限制:1000
内存限制:65536
输入
一行,给出密文,密文不为空,而且其中的字符数不超过200。
输出
输出一行,即密文对应的明文。
样例输入
NS BFW, JAJSYX TK NRUTWYFSHJ FWJ YMJ WJXZQY TK YWNANFQ HFZXJX
样例输出
IN WAR, EVENTS OF IMPORTANCE ARE THE RESULT OF TRIVIAL CAUSES

要解决这个问题,我们可以遍历密文中的每个字符,并根据规则进行解密操作。以下是解决该问题的示例代码:

#include 

void decrypt(char *ciphertext) {
    int i = 0;
    while (ciphertext[i] != '\0') {
        if (ciphertext[i] >= 'A' && ciphertext[i] <= 'Z') {
            // 解密字母
            ciphertext[i] = ((ciphertext[i] - 'A' + 21) % 26) + 'A';
        }
        i++;
    }
}

int main() {
    char ciphertext[201];
    fgets(ciphertext, sizeof(ciphertext), stdin);

    decrypt(ciphertext);

    printf("%s\n", ciphertext);

    return 0;
}

在程序中,我们定义了一个decrypt函数,用于对给定的密文进行解密操作。函数接受一个字符数组ciphertext作为输入。

decrypt函数中,我们遍历密文中的每个字符。如果字符是大写字母,则根据规则进行解密操作。我们将字符减去字母’A’的ASCII值,然后加上21(相当于后移5位,考虑了循环的情况),再对26取余,最后加上字母’A’的ASCII值,即可得到解密后的明文字符。

在主函数中,我们使用fgets函数读取输入的密文,并将其存储到字符数组ciphertext中。

然后,我们调用decrypt函数对密文进行解密操作。

最后,我们使用printf函数输出解密后的明文。

你可以将以上代码保存为一个.c文件,使用C语言编译器进行编译和运行。然后,输入密文,即可得到对应的明文。

第3题:错误探测

给定n*n由0和1组成的矩阵,如果矩阵的每一行和每一列的1的数量都是偶数,则认为符合条件。
你的任务就是检测矩阵是否符合条件,或者在仅改变一个矩阵元素的情况下能否符合条件。
"改变矩阵元素"的操作定义为0变成1或者1变成0。
时间限制:1000
内存限制:65536
输入
输入n + 1行,第1行为矩阵的大小n(0 < n < 100),以下n行为矩阵的每一行的元素,元素之间以一个空格分开。
输出
如果矩阵符合条件,则输出OK; 如果矩阵仅改变一个矩阵元素就能符合条件,则输出需要改变的元素所在的行号和列号,以一个空格分开。 如果不符合以上两条,输出Corrupt。
样例输入
样例输入1
4
1 0 1 0
0 0 0 0
1 1 1 1
0 1 0 1
样例输入2
4
1 0 1 0
0 0 1 0
1 1 1 1
0 1 0 1
样例输入3
4
1 0 1 0
0 1 1 0
1 1 1 1
0 1 0 1
样例输出
样例输出1
OK
样例输出2
2 3
样例输出3
Corrupt

要解决这个问题,我们需要检查矩阵的每一行和每一列中1的数量是否都是偶数。如果是,那么矩阵符合条件。如果不是,我们需要检查是否只有一个元素的改变可以使矩阵符合条件。以下是解决该问题的示例代码:

#include 

int countOnes(int matrix[][100], int n, int row, int col) {
    int count = 0;
    for (int i = 0; i < n; i++) {
        if (matrix[row][i] == 1) {
            count++;
        }
    }
    for (int i = 0; i < n; i++) {
        if (matrix[i][col] == 1) {
            count++;
        }
    }
    return count;
}

int main() {
    int n;
    scanf("%d", &n);

    int matrix[100][100];

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d", &matrix[i][j]);
        }
    }

    int corruptedRow = -1;
    int corruptedCol = -1;
    int corruptedCount = 0;

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            int onesCount = countOnes(matrix, n, i, j);
            if (onesCount % 2 != 0) {
                corruptedCount++;
                corruptedRow = i + 1;
                corruptedCol = j + 1;
            }
        }
    }

    if (corruptedCount == 0) {
        printf("OK\n");
    } else if (corruptedCount == 1) {
        printf("%d %d\n", corruptedRow, corruptedCol);
    } else {
        printf("Corrupt\n");
    }

    return 0;
}

在程序中,我们首先定义了一个辅助函数countOnes,用于计算矩阵中指定行和列中1的数量。函数接受一个二维整数数组matrix、矩阵的大小n、以及要计算的行号row和列号col

countOnes函数中,我们使用两个循环分别计算指定行和列中的1的数量,并将其累加到count变量中。

在主函数中,我们首先使用scanf函数读取输入的矩阵的大小n

然后,我们使用两个嵌套的循环读取输入的矩阵元素,并将其存储到二维整数数组matrix中。

接下来,我们使用两个变量corruptedRowcorruptedCol来记录需要改变的元素所在的行号和列号,初始值设为-1。我们还使用一个变量corruptedCount来记录不符合条件的元素数量,初始值设为0。

然后,我们使用两个嵌套的循环遍历矩阵中的每个元素。对于每个元素,我们调用countOnes函数计算其所在行和列中1的数量。如果1的数量是奇数,说明该元素需要改变,我们将corruptedCount加1,并更新corruptedRowcorruptedCol的值。

最后,我们根据corruptedCount的值输出结果。如果corruptedCount为0,说明矩阵符合条件,输出"OK";如果corruptedCount为1,说明仅改变一个元素就能使矩阵符合条件,输出需要改变的元素所在的行号和列号;否则,输出"Corrupt"表示矩阵不符合条件。

你可以将以上代码保存为一个.c文件,使用C语言编译器进行编译和运行。然后,按照输入要求输入矩阵的大小和具体的矩阵元素,即可得到判断结果。

第4题:奇数单增序列

给定一个长度为N(不大于500)的正整数序列,请将其中的所有奇数取出,并按升序输出。
时间限制:1000
内存限制:65536
输入
共2行: 第1行为 N; 第2行为 N 个正整数,其间用空格间隔。
输出
增序输出的奇数序列,数据之间以逗号间隔。数据保证至少有一个奇数。
样例输入
10
1 3 2 6 5 4 9 8 7 10
样例输出
1,3,5,7,9

要解决这个问题,我们需要遍历给定的正整数序列,将其中的奇数取出,并按升序输出。以下是解决该问题的示例代码:

#include 

void sortOddNumbers(int arr[], int n) {
    // 冒泡排序,按升序排序
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

int main() {
    int n;
    scanf("%d", &n);

    int numbers[500];
    int oddNumbers[500];
    int oddCount = 0;

    for (int i = 0; i < n; i++) {
        scanf("%d", &numbers[i]);
        if (numbers[i] % 2 != 0) {
            oddNumbers[oddCount] = numbers[i];
            oddCount++;
        }
    }

    sortOddNumbers(oddNumbers, oddCount);

    for (int i = 0; i < oddCount; i++) {
        printf("%d", oddNumbers[i]);
        if (i < oddCount - 1) {
            printf(",");
        }
    }
    printf("\n");

    return 0;
}

在程序中,我们首先定义了一个辅助函数sortOddNumbers,用于对奇数序列进行升序排序。函数接受一个整数数组arr和数组的大小n

sortOddNumbers函数中,我们使用冒泡排序算法对奇数序列进行升序排序。

在主函数中,我们首先使用scanf函数读取输入的正整数序列的长度n

然后,我们定义两个数组numbersoddNumbers,分别用于存储输入的正整数序列和奇数序列。我们还定义了一个变量oddCount来记录奇数序列的长度,初始值设为0。

接下来,我们使用一个循环读取输入的正整数序列,并将其中的奇数存储到oddNumbers数组中,并更新oddCount的值。

然后,我们调用sortOddNumbers函数对奇数序列进行升序排序。

最后,我们使用一个循环输出排序后的奇数序列,数据之间以逗号间隔。注意,在输出最后一个数据后不需要输出逗号。

你可以将以上代码保存为一个.c文件,使用C语言编译器进行编译和运行。然后,按照输入要求输入正整数序列,即可得到升序输出的奇数序列。

第5题:话题焦点人物

微博提供了一种便捷的交流平台。一条微博中,可以提及其它用户。例如Lee发出一条微博为:“期末考试顺利 @Kim @Neo”,则Lee提及了Kim和Neo两位用户。
我们收集了N(1 < N < 10000)条微博,并已将其中的用户名提取出来,用小于等于100的正整数表示。
通过分析这些数据,我们希望发现大家的话题焦点人物,即被提及最多的人(题目保证这样的人有且只有一个),并找出那些提及它的人。
时间限制:1000
内存限制:65536
输入
输入共两部分: 第一部分是微博数量N,1 < N < 10000。 第二部分是N条微博,每条微博占一行,表示为: 发送者序号a,提及人数k(0 < = k < = 20),然后是k个被提及者序号b1,b2…bk; 其中a和b1,b2…bk均为大于0小于等于100的整数。相邻两个整数之间用单个空格分隔。
输出
输出分两行: 第一行是被提及最多的人的序号; 第二行是提及它的人的序号,从小到大输出,相邻两个数之间用单个空格分隔。同一个序号只输出一次。
样例输入
5
1 2 3 4
1 0
90 3 1 2 4
4 2 3 2
2 1 3
样例输出
3
1 2 4

要解决这个问题,我们需要统计每个人被提及的次数,并找到被提及次数最多的人,然后输出提及该人物的发送者序号。以下是解决该问题的示例代码:

#include 

int main() {
    int n;
    scanf("%d", &n);

    int mentionedCount[101] = {0};  // 统计每个人被提及的次数
    int maxCount = 0;  // 被提及最多的人的次数

    for (int i = 0; i < n; i++) {
        int sender, count;
        scanf("%d %d", &sender, &count);

        for (int j = 0; j < count; j++) {
            int mentioned;
            scanf("%d", &mentioned);
            mentionedCount[mentioned]++;
            if (mentionedCount[mentioned] > maxCount) {
                maxCount = mentionedCount[mentioned];
            }
        }
    }

    int mentionedPeople[101];
    int mentionedPeopleCount = 0;

    for (int i = 1; i <= 100; i++) {
        if (mentionedCount[i] == maxCount) {
            mentionedPeople[mentionedPeopleCount] = i;
            mentionedPeopleCount++;
        }
    }

    printf("%d\n", mentionedPeople[0]);

    for (int i = 0; i < n; i++) {
        if (mentionedCount[mentionedPeople[0]] == 0) {
            break;
        }
        if (mentionedCount[mentionedPeople[0]] == 1) {
            printf("%d\n", i);
        } else {
            printf("%d ", i);
        }
    }

    return 0;
}

在程序中,我们首先定义了一个大小为101的整数数组mentionedCount,用于统计每个人被提及的次数。数组下标表示人物的序号,数组元素表示被提及的次数,初始值都为0。

然后,我们定义了一个变量maxCount,用于记录被提及最多的人的次数,初始值设为0。

接下来,我们使用一个循环读取每条微博的信息。对于每条微博,我们首先读取发送者的序号sender,然后读取被提及人数count。接下来,我们使用一个嵌套循环读取被提及的人的序号,并更新mentionedCount数组中对应人物的被提及次数。同时,我们检查被提及次数是否超过了当前的最大次数,并更新maxCount的值。

然后,我们定义了一个大小为101的整数数组mentionedPeople,用于存储提及被提及最多的人的发送者序号。我们还定义了一个变量mentionedPeopleCount,用于记录mentionedPeople数组中元素的个数,初始值为0。

接下来,我们使用一个循环遍历mentionedCount数组,找到被提及次数等于maxCount的人,将其序号存储到mentionedPeople数组中,并更新mentionedPeopleCount的值。

最后,我们首先输出被提及最多的人的序号mentionedPeople[0]。然后,我们使用一个循环遍历输入的微博信息,并输出提及被提及最多的人的发送者序号。注意,在输出最后一个发送者序号后不需要输出空格。

你可以将以上代码保存为一个.c文件,使用C语言编译器进行编译和运行。然后,按照输入要求输入微博信息,即可得到被提及最多的人的序号和提及它的人的序号。

你可能感兴趣的:(c语言,c++,算法,等级考试,电子学会)