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

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

第1题:和数

给定一个正整数序列,判断其中有多少个数,等于数列中其他两个数的和。 比如,对于数列1 2 3 4, 这个问题的答案就是2, 因为3 = 2 + 1, 4 = 1 + 3。
时间限制:10000
内存限制:65536
输入
共两行,第一行是数列中数的个数n ( 1 <= n <= 100),第二行是由n个不大于10000的正整数组成的数列,相邻两个整数之间用单个空格隔开。
输出
一个整数,即数列中等于其他两个数之和的数的个数。
样例输入
4
1 2 3 4
样例输出
2

以下是使用C语言编写的程序,用于判断数列中有多少个数等于其他两个数的和:

#include 

int countSumEquals(int arr[], int n) {
    int count = 0;
    
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            for (int k = 0; k < n; k++) {
                if (k != i && k != j && arr[k] == arr[i] + arr[j]) {
                    count++;
                    break;
                }
            }
        }
    }
    
    return count;
}

int main() {
    int n;
    scanf("%d", &n);
    
    int arr[n];
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }
    
    int result = countSumEquals(arr, n);
    printf("%d\n", result);
    
    return 0;
}

该程序使用了三层嵌套的循环。外层循环遍历数列中的每个数,中层循环遍历其他不同的数,内层循环遍历数列中的所有数。

对于每个数列中的数,我们将其与其他两个不同的数相加,并在内层循环中查找是否存在一个数等于这个和。如果找到了,说明该数等于其他两个数的和,计数器count加1,并跳出内层循环。

最后,将计数器count的值打印出来,即为数列中等于其他两个数之和的数的个数。

main函数中,我们首先读取数列中数的个数n,然后读取数列中的每个数,并存储在数组arr中。接着,调用countSumEquals函数计算等于其他两个数之和的数的个数,并将结果打印出来。

使用上述程序,可以实现判断数列中有多少个数等于其他两个数的和,并按要求的格式输出结果。

第2题:生理周期

人生来就有三个生理周期,分别为体力、感情和智力周期,它们的周期长度为23天、28天和33天。每一个周期中有一天是高峰。在高峰这天,人会在相应的方面表现出色。例如,智力周期的高峰,人会思维敏捷,精力容易高度集中。因为三个周期的周长不同,所以通常三个周期的高峰不会落在同一天。对于每个人,我们想知道何时三个高峰落在同一天。对于每个周期,我们会给出从当前年份的第一天开始,到出现高峰的天数(不一定是第一次高峰出现的时间)。你的任务是给定一个从当年第一天开始数的天数,输出从给定时间开始(不包括给定时间)下一次三个高峰落在同一天的时间(距给定时间的天数)。例如:给定时间为10,下次出现三个高峰同天的时间是12,则输出2(注意这里不是3)。
时间限制:1000
内存限制:65536
输入
一行,包含四个整数:p, e, i和d,相邻两个整数之间用单个空格隔开。 p, e, i分别表示体力、情感和智力高峰出现的时间(时间从当年的第一天开始计算)。d 是给定的时间,可能小于p, e, 或 i。 所有给定时间是非负的并且小于等于365, 所求的时间小于等于21252。
输出
一个整数,即从给定时间起,下一次三个高峰同天的时间(距离给定时间的天数)。
样例输入
4 5 6 7
样例输出
16994

以下是使用C语言编写的程序,根据给定的体力、感情和智力高峰出现的时间,以及给定的时间,计算下一次三个高峰落在同一天的时间距离给定时间的天数:

#include 

int calculateNextPeak(int p, int e, int i, int d) {
    int currentDay = d + 1;
    
    while (1) {
        if ((currentDay - p) % 23 == 0 && (currentDay - e) % 28 == 0 && (currentDay - i) % 33 == 0) {
            return currentDay - d;
        }
        
        currentDay++;
    }
}

int main() {
    int p, e, i, d;
    scanf("%d %d %d %d", &p, &e, &i, &d);
    
    int result = calculateNextPeak(p, e, i, d);
    printf("%d\n", result);
    
    return 0;
}

该程序使用了一个循环来逐个增加当前天数,直到找到满足条件的下一个三个高峰同天的时间。

在循环中,我们首先检查当前天数是否满足以下条件:

(1)(currentDay - p) % 23 == 0:表示当前天数减去体力高峰出现的时间后,可以被23整除,即当前天数是体力高峰的一天。

(2)(currentDay - e) % 28 == 0:表示当前天数减去感情高峰出现的时间后,可以被28整除,即当前天数是感情高峰的一天。

(3)(currentDay - i) % 33 == 0:表示当前天数减去智力高峰出现的时间后,可以被33整除,即当前天数是智力高峰的一天。

如果满足以上三个条件,则当前天数是下一次三个高峰同天的时间。

如果不满足条件,则继续增加当前天数,直到找到满足条件的时间为止。

最后,返回下一次三个高峰同天的时间距离给定时间的天数。

main函数中,我们首先读取体力、感情和智力高峰出现的时间以及给定的时间。然后,调用calculateNextPeak函数计算下一次三个高峰同天的时间距离给定时间的天数,并将结果打印出来。

使用上述程序,可以根据给定的时间和高峰出现的时间,计算下一次三个高峰同天的时间距离给定时间的天数,并按要求的格式输出结果。

第3题:矩形数量

给出平面上一些点(少于50个),坐标都是整数(|xi|,|yi| <= 109),有可能重复。问存在多少个以这些点为顶点的平行于坐标轴的不同矩形。(两个矩形如果四个顶点坐标都相同,就算相同的矩形)
时间限制:1000
内存限制:65536
输入
第一行一个整数T(T <= 100)表示测试数据的组数 对于每组数据 第一行一个整数n,表示点的数量 下面n行每行两个整数xi,yi表示点的坐标
输出
T行,每行一个整数表示以这些点为顶点的平行于坐标轴的矩形个数
样例输入
1
7
0 0
0 1
0 2
1 0
1 1
1 2
0 0
样例输出
3
提示
直接穷举即可。

以下是使用C语言编写的程序,用于计算给定点集中以这些点为顶点的平行于坐标轴的不同矩形的数量:

#include 

int countRectangles(int points[][2], int n) {
    int count = 0;
    
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            int x1 = points[i][0];
            int y1 = points[i][1];
            int x2 = points[j][0];
            int y2 = points[j][1];
            
            if (x1 != x2 && y1 != y2) {  // 两个点不在同一条直线上
                int x3 = x2;  // 第三个点的坐标
                int y3 = y1;
                int x4 = x1;
                int y4 = y2;
                
                // 检查第四个点是否存在于点集中
                int found = 0;
                for (int k = 0; k < n; k++) {
                    if (points[k][0] == x3 && points[k][1] == y3) {
                        found = 1;
                        break;
                    }
                }
                
                // 如果第四个点存在于点集中,则找到一个矩形
                if (found) {
                    count++;
                }
            }
        }
    }
    
    return count;
}

int main() {
    int T;
    scanf("%d", &T);
    
    for (int t = 0; t < T; t++) {
        int n;
        scanf("%d", &n);
        
        int points[50][2];
        for (int i = 0; i < n; i++) {
            scanf("%d %d", &points[i][0], &points[i][1]);
        }
        
        int result = countRectangles(points, n);
        printf("%d\n", result);
    }
    
    return 0;
}

该程序使用了两层嵌套的循环,穷举所有可能的点对,并检查是否存在其他两个点与这两个点可以构成一个矩形。

在外层循环中,我们遍历点集中的每个点作为矩形的一个顶点。

在内层循环中,我们遍历点集中剩余的点,作为矩形的另一个顶点。

对于每对点,我们获取它们的坐标,并检查它们是否在同一条直线上。如果它们不在同一条直线上,我们构造另外两个点,使得这四个点可以构成一个矩形。

然后,我们检查第四个点是否存在于点集中。如果存在,则找到一个矩形,计数器count加1。

最后,返回计数器count的值,即为以给定点集为顶点的平行于坐标轴的不同矩形的数量。

main函数中,我们首先读取测试数据的组数T,然后使用一个外层循环处理每组数据。

在每组数据中,我们首先读取点的数量n,然后读取每个点的坐标,并存储在二维数组points中。

接着,调用countRectangles函数计算以给定点集为顶点的平行于坐标轴的不同矩形的数量,并将结果打印出来。

使用上述程序,可以计算给定点集中以这些点为顶点的平行于坐标轴的不同矩形的数量,并按要求的格式输出结果。

第4题:文件结构“图”

在计算机上看到文件系统的结构通常很有用。Microsoft Windows上面的"explorer"程序就是这样的一个例子。但是在有图形界面之前,没有图形化的表示方法的,那时候最好的方式是把目录和文件的结构显示成一个"图"的样子,而且使用缩排的形式来表示目录的结构。比如:
ROOT
| dir1
| file1
| file2
| file3
| dir2
| dir3
| file1
file1
file2
这个图说明:ROOT目录包括三个子目录和两个文件。第一个子目录包含3个文件,第二个子目录是空的,第三个子目录包含一个文件。
时间限制:1000
内存限制:65536
输入
你的任务是写一个程序读取一些测试数据。每组测试数据表示一个计算机的文件结构。每组测试数据以’*‘结尾,而所有合理的输入数据以’#‘结尾。一组测试数据包括一些文件和目录的名字(虽然在输入中我们没有给出,但是我们总假设ROOT目录是最外层的目录)。在输入中,以’]‘表示一个目录的内容的结束。目录名字的第一个字母是’d’,文件名字的第一个字母是’f’。文件名可能有扩展名也可能没有(比如fmyfile.dat和fmyfile)。文件和目录的名字中都不包括空格,长度都不超过30。一个目录下的子目录个数和文件个数之和不超过30。
输出
在显示一个目录中内容的时候,先显示其中的子目录(如果有的话),然后再显示文件(如果有的话)。文件要求按照名字的字母表的顺序显示(目录不用按照名字的字母表顺序显示,只需要按照目录出现的先后显示)。对每一组测试数据,我们要先输出"DATA SET x:",这里x是测试数据的编号(从1开始)。在两组测试数据之间要输出一个空行来隔开。 你需要注意的是,我们使用一个’|'和5个空格来表示出缩排的层次。
样例输入
file1
file2
dir3
dir2
file1
file2
]
]
file4
dir1
]
file3
*
file2
file1
*
#
样例输出
DATA SET 1:
ROOT
| dir3
| | dir2
| | file1
| | file2
| dir1
file1
file2
file3
file4
DATA SET 2:
ROOT
file1
file2
提示
一个目录和它的子目录处于不同的层次 一个目录和它的里面的文件处于同一层次

根据题目要求,我们需要编写一个程序来读取文件结构的测试数据,并按照给定的格式打印目录和文件的层次结构。

下面是一个使用C语言编写的解决方案:

#include 
#include 
#include 

#define MAX_NAME_LENGTH 31
#define MAX_ENTRIES 30
#define MAX_LEVELS 30

typedef struct {
    char name[MAX_NAME_LENGTH];
    int isDirectory;
} Entry;

void printIndent(int level) {
    for (int i = 0; i < level; i++) {
        printf("|     ");
    }
}

int compareEntries(const void* a, const void* b) {
    Entry* entryA = (Entry*)a;
    Entry* entryB = (Entry*)b;
    return strcmp(entryA->name, entryB->name);
}

void printFileStructure(Entry entries[], int numEntries, int level) {
    qsort(entries, numEntries, sizeof(Entry), compareEntries);
    
    for (int i = 0; i < numEntries; i++) {
        printIndent(level);
        printf("%s\n", entries[i].name);
        
        if (entries[i].isDirectory) {
            printIndent(level);
            printf("|\n");
            
            int j = i + 1;
            int numSubDirectories = 0;
            while (j < numEntries && entries[j].isDirectory) {
                numSubDirectories++;
                j++;
            }
            
            printFileStructure(&entries[i + 1], numSubDirectories, level + 1);
            
            i = j - 1;
        }
    }
}

int main() {
    char name[MAX_NAME_LENGTH];
    int dataSet = 1;
    
    while (1) {
        Entry entries[MAX_ENTRIES];
        int numEntries = 0;
        
        while (1) {
            scanf("%s", name);
            
            if (name[0] == '#') {
                return 0;
            }
            
            if (name[0] == '*') {
                printf("\n");
                break;
            }
            
            if (name[0] == ']') {
                break;
            }
            
            Entry entry;
            strcpy(entry.name, name + 1);
            
            if (name[0] == 'd') {
                entry.isDirectory = 1;
            } else {
                entry.isDirectory = 0;
            }
            
            entries[numEntries++] = entry;
        }
        
        printf("DATA SET %d:\n", dataSet++);
        printf("ROOT\n");
        
        printFileStructure(entries, numEntries, 1);
    }
    
    return 0;
}

该程序使用了自定义的Entry结构,用于存储文件和目录的名称以及它们是否是目录。

printIndent函数中,我们使用循环打印缩进符号(| )来表示层次结构的缩进。

compareEntries函数用于比较两个Entry结构,以便在打印时按字母顺序对目录和文件进行排序。

printFileStructure函数用于递归地打印文件结构。它首先对输入的entries数组进行排序,以确保目录和文件按字母顺序打印。然后,它遍历每个条目,并根据条目的类型(目录或文件)进行打印。如果是目录,它会递归调用printFileStructure函数来打印子目录的内容。

main函数中,我们使用一个外层循环来处理每组测试数据。在每组测试数据中,我们首先读取文件和目录的名称,并存储在entries数组中。当遇到'*'时,表示当前组测试数据的结束。当遇到'#'时,表示所有合理的输入数据的结束。

在每组测试数据的开始,我们打印DATA SET x:,其中x是测试数据的编号。然后,我们打印根目录ROOT。接下来,调用printFileStructure函数来打印文件结构。

使用上述程序,可以根据给定的文件结构数据按要求的格式打印目录和文件的层次结构。

第5题:分解因数

给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3 * … * an,并且1 < a1 <= a2 <= a3 <= … <= an,问这样的分解的种数有多少。注意到a = a也是一种分解。
时间限制:1000
内存限制:65536
输入
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a (1 < a < 32768)
输出
n行,每行输出对应一个输入。输出应是一个正整数,指明满足要求的分解的种数
样例输入
2
2
20
样例输出
1
4

下面是使用 C 语言编写的解决方案,用于将给定的正整数进行因数分解并计算分解的种数:

#include 

// 计算正整数 a 的因数分解种数
int factorize(int a) {
    int count = 0;
    for (int i = 2; i <= a; i++) {
        if (a % i == 0) {
            // 找到一个因数 i
            if (i == a) {
                // 若因数为 a 本身,则计数加 1
                count++;
            } else {
                // 若因数不是 a 本身,则递归计算剩余部分的因数分解种数
                count += factorize(a / i);
            }
        }
    }
    return count;
}

int main() {
    int n;
    scanf("%d", &n);  // 输入测试数据组数
    for (int i = 0; i < n; i++) {
        int a;
        scanf("%d", &a);  // 输入正整数 a
        int result = factorize(a);  // 计算分解的种数
        printf("%d\n", result);  // 输出结果
    }
    return 0;
}

上述代码首先定义了一个 factorize 函数,用于计算正整数的因数分解种数。在 main 函数中,根据输入的测试数据组数和每组测试数据,依次调用 factorize 函数计算分解的种数,并输出结果。

请注意,在给定的示例中,分解种数包括了 a = a 本身的情况,因此将 1 纳入结果中计算。如果不希望包括 a = a 的情况,则需要在代码中对 a = a 的情况进行特殊处理。

编译并运行上述代码,即可实现对给定正整数的因数分解种数的计算。

你可能感兴趣的:(C/C++等级考试历届真题解析,c语言,c++,算法,等级考试,电子学会)