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