中国电子学会(CEIT)2020年09月真题C语言软件编程等级考试三级(含详细解析答案)

中国电子学会(CEIT)考评中心历届真题(含解析答案)

C语言软件编程等级考试三级 2020年09月

编程题五道							总分:100分

一、因子问题(20分)

任给两个正整数N、M,求一个最小的正整数a,使得a和(M-a)都是N的因子。

时间限制: 10000ms

内存限制: 65536kb

输入

包括两个整数N、M。N不超过1,000,000。输出

输出一个整数a,表示结果。如果某个案例中满足条件的正整数不存在,则在对应行输出-1

样例输入

c 复制代码
35 10

样例输出

c 复制代码
5
c 复制代码
#include <stdio.h>  // 引入标准输入输出库,用于使用scanf和printf函数

int main() {  // 主函数入口
	int i,m, n;  // 声明三个整型变量i, m, n
	scanf("%d %d", &n, &m);  // 从标准输入读取两个整数,并分别赋值给n和m

	// 使用枚举法来查找满足条件的i
	for(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,则打印-1
	return 0;  // 退出程序,返回0表示正常结束
}
/*
	此代码的目的是找到一个整数i,使得n可以被i和(m-i)整除。
	如果找到了这样的i,则打印出i并结束程序;如果没有找到,
	则打印-1并结束程序。
*/

二、质数的和与积(20分)

两个质数的和是S,它们的积最大是多少?

时间限制: 10000ms

内存限制: 65536kb

输入

一个不大于10000的正整数S,为两个质数的和。输出

一个整数,为两个质数的最大乘积。数据保证有解。

样例输入

c 复制代码
50

样例输出

c 复制代码
589
c 复制代码
#include <stdio.h>  // 引入标准输入输出库,用于printf和scanf函数
#include <math.h>   // 引入数学库,用于sqrt函数

bool judge(int x){ // 定义一个函数,用于判断一个整数x是否为素数
    int i;         // 定义循环变量i
    if(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不是素数,返回false
    return true;  // 如果x不能被2到其平方根之间的任何数整除,那么x是素数,返回true
}

int main() { // 主函数入口
    int i,s;   // 定义循环变量i和输入变量s
    scanf("%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"); // 如果找不到符合条件的素数对,输出-1
    return 0;     // 结束程序
}

三、扩号匹配问题(20分)

在某个字符串(长度不超过100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$"标注,不能匹配的右括号用"?"标注.

时间限制: 3000ms

内存限制: 65536kb

输入

输入包括多组数据,每组数据一行,包含一个字符串,只包含左右括号和大小写字母,字符串长度不超过100

输出

对每组输出数据,输出两行,第一行包含原始输入字符,第二行由"$""?"和空格组成,"$""?"表示与之对应的左括号和右括号不能匹配。

样例输入

c 复制代码
((ABCD(x)
)(rttyy())sss)(

样例输出

c 复制代码
((ABCD(x)
$$
)(rttyy())sss)(
?            ?$
c 复制代码
#include <stdio.h>  // 引入标准输入输出头文件,这样我们可以使用scanf和printf等函数
#include <string.h> // 引入字符串处理头文件
#define N 105        // 定义一个常量N,用于指定数组的最大长度

int main() {         // 主函数开始
	int i,j,n;         // 定义三个整型变量i, j, n
	char s[N] = " ";   // 定义一个字符数组s,长度为N,初始化为一个空格
	int flag[N];       // 定义一个整型数组flag,用于标记括号的位置

	while (scanf("%s", s)!= EOF) { // 使用scanf读取字符串,直到遇到文件结束符EOF
		n = strlen(s);   // 获取字符串s的长度

		// 将字符串中的括号转换为对应的标记
		for (i = 0; i < n; i++){
			if (s[i]== '(')  // 如果是左括号,标记为1
				flag[i]= 1;
			else if (s[i]== ')') // 如果是右括号,标记为-1
				flag[i]= -1;
			else
				flag[i] = 0;  // 其他字符标记为0
		}

		// 遍历字符串,处理右括号
		for (i = 0; i < n; i++){
			if (flag[i] == -1){
				// 如果当前字符是右括号,向前搜索匹配的左括号
				for (j = i - 1; j >= 0; j--){
					if (flag[j] == 1) {
						// 如果找到匹配的左括号,将两个括号标记为0
						flag[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行,即名名吃巧克力的方案数。

样例输入

c 复制代码
4

样例输出

c 复制代码
5
c 复制代码
#include<stdio.h>  // 引入标准输入输出库,这样我们可以使用scanf和printf等函数

// 定义一个函数func,它接受一个整数n作为参数,并返回斐波那契数列中第n项的值
int func(int n){
	if(n==1)  // 如果n等于1
		return 1;  // 返回斐波那契数列的第1项,即1
	if(n==2)  // 如果n等于2
		return 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*22*2的砖去铺满。问有多少种不同的方式。

时间限制: 3000ms

内存限制: 131072kb

输入

整个测试有多组数据,请做到文件底结束。每行给出一个数字N,0 <=n<= 250

输出

如题

样例输入

c 复制代码
2
8
12
100
200

样例输出

c 复制代码
3
171
2731
845100400152152934331135470251
1071292029505993517027974728227441735014801995855195223534251
c 复制代码
#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;

    // 初始化进位标志为0
    f = 0;

    // 将字符串a和b转换为整数数组af和bf
    for (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增加1
    if (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为0
    while (true) {
        scanf("%d", &n);
        if (n == 0)
            break;
        printf("%s\n", dp[n]);
    }

    return 0;
}
/*
	程序的主要逻辑是计算一个特定斐波那契数列的变种,其中每个数字是前两个数字之和的两倍。
	程序首先初始化前两个数字,然后使用循环计算后续的数字,并将它们存储在dp数组中。然后,
	程序进入一个无限循环,不断从标准输入读取一个数字n,并打印出dp[n]的值,直到用户输入0为止。
*/

	
相关推荐
tinker在coding29 分钟前
Coding Caprice - Linked-List 1
算法·leetcode
唐诺5 小时前
几种广泛使用的 C++ 编译器
c++·编译器
XH华5 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生5 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_5 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
落魄君子6 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
冷眼看人间恩怨6 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
菜鸡中的奋斗鸡→挣扎鸡6 小时前
滑动窗口 + 算法复习
数据结构·算法
红龙创客6 小时前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
Lenyiin6 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin