中国电子学会(CEIT)考评中心历届真题(含解析答案)
C语言软件编程等级考试三级 2020年09月
编程题五道 总分:100分
一、因子问题(20分)
任给两个正整数N、M,求一个最小的正整数a,使得a和(M-a)都是N的因子。
时间限制: 10000ms
内存限制: 65536kb
输入
包括两个整数N、M。N不超过1,000,000。输出
输出一个整数a,表示结果。如果某个案例中满足条件的正整数不存在,则在对应行输出-1
样例输入
35 10
样例输出
5
#include <stdio.h> // 引入标准输入输出库,用于使用scanf和printf函数int main() { // 主函数入口int i,m, n; // 声明三个整型变量i, m, nscanf("%d %d", &n, &m); // 从标准输入读取两个整数,并分别赋值给n和m// 使用枚举法来查找满足条件的ifor(i = 1; i < n; i++) { // 初始化i为1,并在每次迭代后递增,直到i大于n时停止if(n % i == 0 && n % (m - i) == 0) { // 检查n是否能被i整除,并且n是否能被(m-i)整除printf("%d", i); // 如果满足条件,打印i的值return 0; // 退出程序,返回0表示正常结束}}printf("-1"); // 如果循环结束后没有找到满足条件的i,则打印-1return 0; // 退出程序,返回0表示正常结束
}
/*此代码的目的是找到一个整数i,使得n可以被i和(m-i)整除。如果找到了这样的i,则打印出i并结束程序;如果没有找到,则打印-1并结束程序。
*/
二、质数的和与积(20分)
两个质数的和是S,它们的积最大是多少?
时间限制: 10000ms
内存限制: 65536kb
输入
一个不大于10000的正整数S,为两个质数的和。输出
一个整数,为两个质数的最大乘积。数据保证有解。
样例输入
50
样例输出
589
#include <stdio.h> // 引入标准输入输出库,用于printf和scanf函数
#include <math.h> // 引入数学库,用于sqrt函数bool judge(int x){ // 定义一个函数,用于判断一个整数x是否为素数int i; // 定义循环变量iif(x==2) return false; // 如果x为2,返回false,因为2是唯一的偶数素数for(i=2; i<=sqrt(x); i++) // 从2开始,到x的平方根(包含),遍历所有可能的因子if(x%i==0) // 如果x能被i整除return false; // 则x不是素数,返回falsereturn true; // 如果x不能被2到其平方根之间的任何数整除,那么x是素数,返回true
}int main() { // 主函数入口int i,s; // 定义循环变量i和输入变量sscanf("%d" ,&s); // 从标准输入读取一个整数,并存储在变量s中for(i=s/2; i>=2; i--){ // 从s/2开始,递减到2,遍历所有可能的数if(judge(i)&&judge(s-i)){ // 判断i和s-i是否都是素数printf("%d \n",i*(s-i)); // 如果是,输出它们的乘积,并结束程序return 0;}}printf("-1"); // 如果找不到符合条件的素数对,输出-1return 0; // 结束程序
}
三、扩号匹配问题(20分)
在某个字符串(长度不超过100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$"
标注,不能匹配的右括号用"?"
标注.
时间限制: 3000ms
内存限制: 65536kb
输入
输入包括多组数据,每组数据一行,包含一个字符串,只包含左右括号和大小写字母,字符串长度不超过100
输出
对每组输出数据,输出两行,第一行包含原始输入字符,第二行由"$"
,"?"
和空格组成,"$"
和"?"
表示与之对应的左括号和右括号不能匹配。
样例输入
((ABCD(x)
)(rttyy())sss)(
样例输出
((ABCD(x)
$$
)(rttyy())sss)(
? ?$
#include <stdio.h> // 引入标准输入输出头文件,这样我们可以使用scanf和printf等函数
#include <string.h> // 引入字符串处理头文件
#define N 105 // 定义一个常量N,用于指定数组的最大长度int main() { // 主函数开始int i,j,n; // 定义三个整型变量i, j, nchar s[N] = " "; // 定义一个字符数组s,长度为N,初始化为一个空格int flag[N]; // 定义一个整型数组flag,用于标记括号的位置while (scanf("%s", s)!= EOF) { // 使用scanf读取字符串,直到遇到文件结束符EOFn = strlen(s); // 获取字符串s的长度// 将字符串中的括号转换为对应的标记for (i = 0; i < n; i++){if (s[i]== '(') // 如果是左括号,标记为1flag[i]= 1;else if (s[i]== ')') // 如果是右括号,标记为-1flag[i]= -1;elseflag[i] = 0; // 其他字符标记为0}// 遍历字符串,处理右括号for (i = 0; i < n; i++){if (flag[i] == -1){// 如果当前字符是右括号,向前搜索匹配的左括号for (j = i - 1; j >= 0; j--){if (flag[j] == 1) {// 如果找到匹配的左括号,将两个括号标记为0flag[i] = 0;flag[j] = 0;break; // 跳出内层循环}}}}printf("%s\n",s); // 输出处理前的字符串// 根据标记数组打印结果for (i = 0; i < n; i++){if (flag[i] == 0)printf(" "); // 如果是空格或已匹配的括号,输出空格else if(flag[i]== 1)printf("$"); // 如果是左括号,输出$else if (flag[i]== -1)printf("?"); // 如果是未匹配的右括号,输出?}printf("\n"); // 输出换行符}return 0; // 主函数返回0,表示程序正常结束
}
/*程序的目的是处理用户输入的字符串,其中包含左括号'('和右括号')'。程序会标记出每个括号的位置,并检查是否有未匹配的右括号。如果有未匹配的右括号,程序会在输出时将其替换为'?',而匹配的括号对会被替换为空格。左括号会被替换为'$'。
*/
四、吃糖果(20分)
名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有N块巧克力,20>N>0)。妈妈告诉名名每天可以吃一块或者两块巧克力。假设名名每天都吃巧克力,问名名共有多少种不同的吃完巧克力的方案。
例如:
如果N=1,则名名第1天就吃掉它,共有1种方案;
如果N=2,则名名可以第1天吃1块,第2天吃1块,也可以第1天吃2块,共有2种方案;
如果N=3,则名名第1天可以吃1块,剩2块,也可以第1天吃2块剩1块,所以名名共有2+1=3种方案;
如果N=4,则名名可以第1天吃1块,剩3块,也可以第1天吃2块,剩2块,共有3+2=5种方案。
现在给定N,请你写程序求出名名吃巧克力的方案数目。
时间限制: 1000ms
内存限制: 65536kb
输入
输入只有1行,即整数N。
输出
输出只有1行,即名名吃巧克力的方案数。
样例输入
4
样例输出
5
#include<stdio.h> // 引入标准输入输出库,这样我们可以使用scanf和printf等函数// 定义一个函数func,它接受一个整数n作为参数,并返回斐波那契数列中第n项的值
int func(int n){if(n==1) // 如果n等于1return 1; // 返回斐波那契数列的第1项,即1if(n==2) // 如果n等于2return 2; // 返回斐波那契数列的第2项,即2// 如果n不是1也不是2,那么返回前两项的和,即func(n-1) + func(n-2)return func(n-1)+func(n-2);
}// main函数,程序的入口点
int main() {int n; // 定义一个整数变量n,用于存储用户输入的数字scanf("%d",&n); // 使用scanf函数从标准输入读取一个整数,并将其存储在变量n中printf("%d",func(n)); // 使用printf函数输出斐波那契数列中第n项的值return 0; // 表示程序正常结束
}
/*实现是基于递归的,对于较大的n值,它的效率会非常低,因为它会重复计算很多相同的子问题。在实际应用中,通常会使用其他方法来提高计算斐波那契数列的效率,比如动态规划或缓存已计算的值。
*/
五、铺砖(20分)
对于一个2行N列的走道。现在用1*2
,2*2
的砖去铺满。问有多少种不同的方式。
时间限制: 3000ms
内存限制: 131072kb
输入
整个测试有多组数据,请做到文件底结束。每行给出一个数字N,0 <=n<= 250
输出
如题
样例输入
2
8
12
100
200
样例输出
3
171
2731
845100400152152934331135470251
1071292029505993517027974728227441735014801995855195223534251
#include <stdio.h> // 引入标准输入输出库,这样我们可以使用scanf和printf等函数
#include <string.h> // 引入字符串处理头文件// 大数相加函数
void Ladd(const char *a, const char *b, char *res) {int an, bn, k, f, i, j;int af[300] = {0}, bf[300] = {0}, c[300] = {0};// 获取字符串a和b的长度an = strlen(a);bn = strlen(b);// k为较长的字符串长度k = an > bn ? an : bn;// 初始化进位标志为0f = 0;// 将字符串a和b转换为整数数组af和bffor (i = 0; i < an; i++)af[i] = a[an - i - 1] - '0';for (i = 0; i < bn; i++)bf[i] = b[bn - i - 1] - '0';// 执行大数相加for (i = 0; i < k; i++) {c[i] += (af[i] + bf[i]) % 10; // 个位数相加c[i + 1] += (af[i] + bf[i]) / 10; // 进位}// 如果最高位有进位,则k增加1if (c[i] != 0)k++;// 将结果数组c转换为字符串并存储到res中for (i = k - 1, j = 0; i >= 0; i--) {res[j++] = c[i] + '0';}
}char dp[300][300]; // 存储斐波那契数列变种的数组int main() {int n;char res[300];// 初始化前两个数字strcpy(dp[0], "1");strcpy(dp[1], "1");strcpy(dp[2], "3");// 根据公式d[i] = d[i-1] + d[i-2] * 2推导数列// 计算斐波那契数列的变种for (int i = 3; i <= 250; i++) { memset(res, 0, sizeof(res)); // 清零结果字符串Ladd(dp[i - 2], dp[i - 2], res); // d[i-2]的两倍Ladd(dp[i - 1], res, res); // 加上d[i-1]strcpy(dp[i], res); // 存储结果}// 从标准输入读取n,并打印dp[n]直到n为0while (true) {scanf("%d", &n);if (n == 0)break;printf("%s\n", dp[n]);}return 0;
}
/*程序的主要逻辑是计算一个特定斐波那契数列的变种,其中每个数字是前两个数字之和的两倍。程序首先初始化前两个数字,然后使用循环计算后续的数字,并将它们存储在dp数组中。然后,程序进入一个无限循环,不断从标准输入读取一个数字n,并打印出dp[n]的值,直到用户输入0为止。
*/