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]; // 数字串最大长度为60scanf("%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// 将中心位置的细菌数设置为mint 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
函数打印细菌分布情况。
在主函数中,我们首先读取输入的m
和n
。然后,我们初始化培养皿的细菌分布情况,将中心位置的细菌数设置为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 100void 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
函数中,我们首先去除字符串开头和结尾的空格。然后,我们反转整个字符串,将字符串的开头和结尾进行交换,依次交换直到中间位置。接下来,我们通过两个指针wordStart
和wordEnd
来记录每个单词的起始位置和结束位置。当遇到空格时,我们反转当前单词,然后更新wordStart
和wordEnd
为下一个单词的起始位置。最后,我们再次反转最后一个单词。
在主函数中,我们使用fgets
函数读取输入的字符串,并去除字符串末尾的换行符。然后,我们调用reverseWords
函数将单词顺序倒排,并使用printf
函数输出结果。
你可以将以上代码保存为一个.c
文件,使用C语言编译器进行编译和运行。然后,输入要进行单词倒排的字符串,即可得到按要求排序后的字符串。