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

在这里插入图片描述

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

第1题:循环数

若一个n位的数字串满足下述条件,则称其是循环数(cyclic):将这个数字串视为整数(可能带有前导0),并用任意一个 1 到 n 之间(包含1和n)的整数去乘它时, 会得到一个将原数字串首尾相接后,再在某处断开而得到的新数字串所对应的整数。例如,数字 142857 是循环数,
因为:
142857 *1 = 142857
142857 *2 = 285714
142857 *3 = 428571
142857 *4 = 571428
142857 *5 = 714285
142857 *6 = 857142。
请写一个程序判断给定的数是否是循环数。
注意:在此题中,输入数字串允许带前导0,且前导0不能被忽略,例如“01”是两位数字串,而“1”是一位数字串。但将数字串转化为整数做乘法运算或比较运算时,可以忽略前导0。
时间限制:10000
内存限制:65536
输入
一行,一个长度在 2 到 60 位之间的数字串。
输出
一个整数,若输入的数字串是循环数,输出1,否则输出0。
样例输入
142857
样例输出
1

你可以使用C语言编写一个程序来判断给定的数是否是循环数。以下是示例代码:

#include <stdio.h>
#include <string.h>

int isCyclicNumber(const char* num) {
    
    
    int n = strlen(num);
    char concatenated[2 * n + 1]; // 存储首尾相接的新数字串
    int i, j;

    for (i = 1; i <= n; i++) {
    
    
        // 将原数字串首尾相接拼接成新数字串
        strncpy(concatenated, num + i - 1, n - i + 1);
        strncpy(concatenated + n - i + 1, num, i);
        concatenated[2 * n] = '\0';

        // 将新数字串转化为整数并与原数字串进行比较
        int original = atoi(num);
        int multiplied = atoi(concatenated);
        if (original * i != multiplied) {
    
    
            return 0; // 不满足循环数条件,返回0
        }
    }

    return 1; // 满足循环数条件,返回1
}

int main() {
    
    
    char num[61]; // 数字串最大长度为60
    scanf("%s", num);

    int result = isCyclicNumber(num);

    printf("%d\n", result);

    return 0;
}

在主函数中,我们声明了字符数组num,用于存储输入的数字串。

接下来,我们定义了一个辅助函数isCyclicNumber用于判断给定的数是否是循环数。函数的参数是一个指向字符数组的指针。

在函数内部,我们首先获取数字串的长度n,并声明一个新的字符数组concatenated用于存储首尾相接的新数字串。

然后,我们使用一个循环从1到n,依次拼接新数字串,并将其转化为整数。

在每次循环中,我们将原数字串首尾相接拼接成新数字串,并将其转化为整数。然后,我们将原数字与该整数进行比较。如果不相等,说明不满足循环数条件,返回0。

如果循环结束后都满足循环数条件,返回1。

最后,在主函数中,我们调用isCyclicNumber函数,传入输入的数字串作为参数,得到判断结果,并输出。

你可以将以上代码保存为一个.c文件,使用C语言编译器编译运行,输入一个数字串,即可得到判断结果的输出。

第2题:合影效果

小云和朋友们去爬香山,为美丽的景色所陶醉,想合影留念。如果他们站成一排,男生全部在左(从拍照者的角度),并按照从矮到高的顺序从左到右排,女生全部在右,并按照从高到矮的顺序从左到右排,请问他们合影的效果是什么样的(所有人的身高都不同)?
时间限制:1000
内存限制:65536
输入
第一行是人数n(2 <= n <= 40,且至少有1个男生和1个女生)。 后面紧跟n行,每行输入一个人的性别(男male或女female)和身高(浮点数,单位米),两个数据之间以空格分隔。
输出
n个浮点数,模拟站好队后,拍照者眼中从左到右每个人的身高。每个浮点数需保留到小数点后2位,相邻两个数之间用单个空格隔开。
样例输入
6
male 1.72
male 1.78
female 1.61
male 1.65
female 1.70
female 1.56
样例输出
1.65 1.72 1.78 1.70 1.61 1.56

你可以使用C语言编写一个程序来模拟小云和朋友们合影的效果。以下是示例代码:

#include <stdio.h>
#include <string.h>

typedef struct {
    
    
    char gender[10]; // 性别
    float height; // 身高
} Person;

int compareHeight(const void* a, const void* b) {
    
    
    const Person* personA = (const Person*)a;
    const Person* personB = (const Person*)b;

    if (strcmp(personA->gender, "male") == 0 && strcmp(personB->gender, "female") == 0) {
    
    
        return -1; // 男生排在前面
    } else if (strcmp(personA->gender, "female") == 0 && strcmp(personB->gender, "male") == 0) {
    
    
        return 1; // 女生排在后面
    } else if (personA->height < personB->height) {
    
    
        return -1; // 身高矮的排在前面
    } else if (personA->height > personB->height) {
    
    
        return 1; // 身高高的排在后面
    } else {
    
    
        return 0; // 身高相同,保持原有顺序
    }
}

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

    Person people[n];
    int i;

    for (i = 0; i < n; i++) {
    
    
        scanf("%s %f", people[i].gender, &people[i].height);
    }

    qsort(people, n, sizeof(Person), compareHeight);

    for (i = 0; i < n; i++) {
    
    
        printf("%.2f ", people[i].height);
    }
    printf("\n");

    return 0;
}

在程序中,我们首先定义了一个结构体Person,表示一个人的性别和身高。

然后,我们定义了一个辅助函数compareHeight,用于比较两个人的身高。在比较过程中,我们首先判断性别,男生排在前面,女生排在后面。如果两个人的性别相同,则比较身高,身高矮的排在前面,身高高的排在后面。如果两个人的性别和身高都相同,则保持原有顺序。

在主函数中,我们首先读取输入的人数n,并声明一个大小为n的Person数组用于存储每个人的信息。

然后,我们使用一个循环逐个读取每个人的性别和身高,并将其存储在数组中。

接下来,我们使用qsort函数对数组进行排序,排序函数使用了之前定义的compareHeight函数作为排序规则。

最后,我们使用循环输出排序后的每个人的身高,保留两位小数,并在相邻两个数之间用单个空格隔开。

你可以将以上代码保存为一个.c文件,使用C语言编译器编译运行,按照要求输入人数和每个人的性别和身高,即可得到模拟合影效果的输出结果。

第3题:大整数加法

求两个不超过200位的非负整数的和。
时间限制:1000
内存限制:65536
输入
有两行,每行是一个不超过200位的非负整数,可能有多余的前导0。
输出
一行,即相加后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。
样例输入
22222222222222222222
33333333333333333333
样例输出
55555555555555555555

对于大整数加法,可以使用数组或字符串来表示和计算。以下是使用字符串的示例代码:

#include <stdio.h>
#include <string.h>

void removeLeadingZeros(char* num) {
    
    
    int len = strlen(num);
    int i, j;

    // 找到第一个非零字符的位置
    for (i = 0; i < len; i++) {
    
    
        if (num[i] != '0') {
    
    
            break;
        }
    }

    // 移动非零字符到数组的起始位置
    for (j = 0; i < len; i++, j++) {
    
    
        num[j] = num[i];
    }

    num[j] = '\0'; // 设置新的字符串结束符
}

void reverseString(char* str) {
    
    
    int len = strlen(str);
    int i, j;

    for (i = 0, j = len - 1; i < j; i++, j--) {
    
    
        char temp = str[i];
        str[i] = str[j];
        str[j] = temp;
    }
}

void addBigIntegers(const char* num1, const char* num2, char* result) {
    
    
    int len1 = strlen(num1);
    int len2 = strlen(num2);
    int maxLength = (len1 > len2) ? len1 : len2;

    int carry = 0; // 进位
    int i;

    for (i = 0; i < maxLength; i++) {
    
    
        int digit1 = (i < len1) ? (num1[len1 - i - 1] - '0') : 0;
        int digit2 = (i < len2) ? (num2[len2 - i - 1] - '0') : 0;

        int sum = digit1 + digit2 + carry;
        result[i] = sum % 10 + '0'; // 计算当前位的数字
        carry = sum / 10; // 计算进位
    }

    if (carry > 0) {
    
    
        result[maxLength] = carry + '0'; // 添加最高位的进位
        result[maxLength + 1] = '\0';
    } else {
    
    
        result[maxLength] = '\0';
    }

    reverseString(result); // 反转字符串得到正确的结果
}

int main() {
    
    
    char num1[201]; // 存储第一个大整数
    char num2[201]; // 存储第二个大整数

    scanf("%s", num1);
    scanf("%s", num2);

    char result[202]; // 存储计算结果

    addBigIntegers(num1, num2, result);

    removeLeadingZeros(result);

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

    return 0;
}

在程序中,我们首先定义了一系列辅助函数:

  • removeLeadingZeros 函数用于移除结果中的前导零。

  • reverseString 函数用于反转字符串。

  • addBigIntegers 函数用于计算两个大整数的和。

addBigIntegers 函数中,我们首先找到输入数字的长度,并确定最长的长度。然后,我们逐位相加,并将结果存储在结果字符串中。我们使用 carry 变量来跟踪进位。

最后,我们在主函数中读取两个输入数字,并调用 addBigIntegers 函数计算它们的和。然后,我们使用 removeLeadingZeros 函数移除结果中的前导零,并输出结果。

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

第4题:细菌的繁殖与扩散

在边长为9的正方形培养皿中,正中心位置有m个细菌。假设细菌的寿命仅一天,但每天可繁殖10个后代,而且这10个后代,有两个分布在原来的单元格中,其余的均匀分布在其四周相邻的八个单元格中。求经过n(1≤n≤4)天后,细菌在培养皿中的分布情况。
时间限制:10000
内存限制:65536
输入
输入为两个整数,第一个整数m表示中心位置细菌的个数(2 ≤ m ≤ 30),第二个整数n表示经过的天数(1 ≤ n ≤ 4)。
输出
输出九行九列整数矩阵,每行的整数之间用空格分隔。整个矩阵代表n天后细菌在培养皿上的分布情况。
样例输入
2 1
样例输出
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 2 2 2 0 0 0
0 0 0 2 4 2 0 0 0
0 0 0 2 2 2 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0

要解决这个问题,我们可以使用一个二维数组来表示培养皿,并模拟细菌的繁殖与扩散过程。以下是解决该问题的示例代码:

#include <stdio.h>

#define SIZE 9 // 培养皿的边长

void printDish(int dish[SIZE][SIZE]) {
    
    
    for (int i = 0; i < SIZE; i++) {
    
    
        for (int j = 0; j < SIZE; j++) {
    
    
            printf("%d ", dish[i][j]);
        }
        printf("\n");
    }
}

void simulateBacteria(int dish[SIZE][SIZE], int m, int n) {
    
    
    int temp[SIZE][SIZE]; // 临时数组用于保存每一天的细菌分布情况

    // 将初始细菌分布复制到临时数组
    for (int i = 0; i < SIZE; i++) {
    
    
        for (int j = 0; j < SIZE; j++) {
    
    
            temp[i][j] = dish[i][j];
        }
    }

    // 模拟细菌的繁殖与扩散过程
    for (int day = 1; day <= n; day++) {
    
    
        // 遍历培养皿上的每个单元格
        for (int i = 0; i < SIZE; i++) {
    
    
            for (int j = 0; j < SIZE; j++) {
    
    
                // 如果当前单元格有细菌
                if (temp[i][j] > 0) {
    
    
                    // 细菌繁殖数量
                    int offspring = temp[i][j] * 10;

                    // 将两个后代细菌分布在原来的单元格
                    temp[i][j] += 2;

                    // 将剩余的细菌均匀分布在相邻的八个单元格
                    if (i > 0) {
    
    
                        temp[i - 1][j] += offspring / 8;
                    }
                    if (i < SIZE - 1) {
    
    
                        temp[i + 1][j] += offspring / 8;
                    }
                    if (j > 0) {
    
    
                        temp[i][j - 1] += offspring / 8;
                    }
                    if (j < SIZE - 1) {
    
    
                        temp[i][j + 1] += offspring / 8;
                    }
                    if (i > 0 && j > 0) {
    
    
                        temp[i - 1][j - 1] += offspring / 8;
                    }
                    if (i > 0 && j < SIZE - 1) {
    
    
                        temp[i - 1][j + 1] += offspring / 8;
                    }
                    if (i < SIZE - 1 && j > 0) {
    
    
                        temp[i + 1][j - 1] += offspring / 8;
                    }
                    if (i < SIZE - 1 && j < SIZE - 1) {
    
    
                        temp[i + 1][j + 1] += offspring / 8;
                    }
                }
            }
        }

        // 将临时数组复制回培养皿数组
        for (int i = 0; i < SIZE; i++) {
    
    
            for (int j = 0; j < SIZE; j++) {
    
    
                dish[i][j] = temp[i][j];
            }
        }
    }
}

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

    int dish[SIZE][SIZE] = {
    
    0}; // 初始化培养皿为全0

    // 将中心位置的细菌数设置为m
    int center = SIZE / 2;
    dish[center][center] = m;

    simulateBacteria(dish, m, n);

    printDish(dish);

    return 0;
}

在程序中,我们首先定义了一个printDish函数,它用于打印培养皿的细菌分布情况。

然后,我们定义了一个simulateBacteria函数,它用于模拟细菌的繁殖与扩散过程。函数接受一个二维数组dish表示培养皿,整数m表示中心位置细菌的个数,整数n表示经过的天数。

simulateBacteria函数中,我们首先复制初始细菌分布情况到临时数组temp。然后,我们依次模拟每一天的细菌繁殖与扩散过程。对于培养皿上的每个单元格,如果当前单元格有细菌,我们根据规则计算细菌的繁殖数量以及后代细菌的分布情况,并更新临时数组temp

完成模拟后,我们将临时数组temp复制回培养皿数组dish,然后调用printDish函数打印细菌分布情况。

在主函数中,我们首先读取输入的mn。然后,我们初始化培养皿的细菌分布情况,将中心位置的细菌数设置为m。接下来,我们调用simulateBacteria函数模拟细菌的繁殖与扩散过程,并输出最终的细菌分布情况。

你可以将以上代码保存为一个.c文件,使用C语言编译器进行编译和运行。然后,按照要求输入中心位置的细菌个数m和经过的天数n,即可得到细菌在培养皿中的分布情况。

第5题:单词倒排

编写程序,读入一行英文(只包含字母和空格,单词间以单个空格分隔),将所有单词的顺序倒排并输出,依然以单个空格分隔。
时间限制:10000
内存限制:65536
输入
输入为一个字符串(字符串长度至多为100)。
输出
输出为按要求排序后的字符串。
样例输入
I am a student
样例输出
student a am I

要解决这个问题,我们可以使用字符串处理的方法来实现单词的倒排。以下是解决该问题的示例代码:

#include <stdio.h>
#include <string.h>

#define MAX_LENGTH 100

void reverseWords(char *str) {
    
    
    int length = strlen(str);
    int start = 0;
    int end = length - 1;

    // 去除开头和结尾的空格
    while (str[start] == ' ') {
    
    
        start++;
    }

    while (str[end] == ' ') {
    
    
        end--;
    }

    // 反转整个字符串
    for (int i = start; i <= (start + end) / 2; i++) {
    
    
        char temp = str[i];
        str[i] = str[start + end - i];
        str[start + end - i] = temp;
    }

    int wordStart = start;
    int wordEnd = start;

    // 反转每个单词
    for (int i = start; i <= end; i++) {
    
    
        if (str[i] == ' ') {
    
    
            // 当遇到空格时,反转单词
            for (int j = wordStart; j <= (wordStart + wordEnd) / 2; j++) {
    
    
                char temp = str[j];
                str[j] = str[wordStart + wordEnd - j];
                str[wordStart + wordEnd - j] = temp;
            }

            wordStart = i + 1;
            wordEnd = i + 1;
        } else {
    
    
            wordEnd = i;
        }
    }

    // 反转最后一个单词
    for (int j = wordStart; j <= (wordStart + wordEnd) / 2; j++) {
    
    
        char temp = str[j];
        str[j] = str[wordStart + wordEnd - j];
        str[wordStart + wordEnd - j] = temp;
    }
}

int main() {
    
    
    char str[MAX_LENGTH];
    fgets(str, MAX_LENGTH, stdin);

    // 去除换行符
    if (str[strlen(str) - 1] == '\n') {
    
    
        str[strlen(str) - 1] = '\0';
    }

    reverseWords(str);

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

    return 0;
}

在程序中,我们首先定义了一个reverseWords函数,它用于将输入的字符串中的单词顺序倒排。函数接受一个字符数组str作为输入。

reverseWords函数中,我们首先去除字符串开头和结尾的空格。然后,我们反转整个字符串,将字符串的开头和结尾进行交换,依次交换直到中间位置。接下来,我们通过两个指针wordStartwordEnd来记录每个单词的起始位置和结束位置。当遇到空格时,我们反转当前单词,然后更新wordStartwordEnd为下一个单词的起始位置。最后,我们再次反转最后一个单词。

在主函数中,我们使用fgets函数读取输入的字符串,并去除字符串末尾的换行符。然后,我们调用reverseWords函数将单词顺序倒排,并使用printf函数输出结果。

你可以将以上代码保存为一个.c文件,使用C语言编译器进行编译和运行。然后,输入要进行单词倒排的字符串,即可得到按要求排序后的字符串。

猜你喜欢

转载自blog.csdn.net/gozhuyinglong/article/details/132700673
今日推荐