中国电子学会(CEIT)考评中心历届真题(含解析答案)
C语言软件编程等级考试三级 2020年12月
编程题五道 总分:100分
一、完美立方(20分)
形如1、完美立方
形如a^3= b^3+ c^3 +d^3
的等式被称为完美立方等式。例如12^3= 6^3+8^3+10^3
。编写一个程序,对任给的正整数N(N≤100),寻找所有的四元组(a, b, c, d),使得a^3= b^3+ c^3+ d^3
,其中a, b, c,d大于1,小于等于N,且b<=c<=d。
时间限制: 1000ms
内存限制: 65536kb
输入
一个正整数N(N≤100)。
输出
每行输出一个完美立方。输出格式为: Cube = a, Triple = (b,c,d)其中a, b, c,d所在位置分别用实际求出四元组值代入。请按照a的值,从小到大依次输出。当两个完美立方等式中a的值相同,则b值小的优先输出、仍相同则c值小的优先输出、再相同则d值小的先输出。
样例输入
24
样例输出
Cube = 6,Triple = (3,4,5)
Cube = 12,Triple = (6,8,10)
Cube = 18,Triple = (2,12,16)
Cube = 18,Triple = (9,12,15)
Cube = 19,Triple = (3,10,18)
Cube = 20,Triple = (7,14,17)
Cube = 24, Triple = (12,16,20)
#include<stdio.h> // 引入标准输入输出库,用于printf和scanf函数
#include<math.h> // 引入数学库,用于pow函数int main() { // 主函数入口int a,b,c,d; // 声明四个整数变量a, b, c, dint n; // 声明一个整数变量n,用于存储用户输入的上限scanf("%d",&n); // 从标准输入读取一个整数,并将其存储在变量n中// 使用枚举法,从2开始到n,逐个检查每个可能的a的值for(a=2; a<=n; a++){// 对于每个a,从2开始到a-1,逐个检查每个可能的b的值for(b=2; b<a; b++){// 对于每个b,从b开始到a-1,逐个检查每个可能的c的值for(c=b; c<a; c++){// 对于每个c,从c开始到a-1,逐个检查每个可能的d的值for(d=c; d<a; d++){// 检查是否满足a的立方等于b、c、d的立方和if(pow(a,3)==pow(b,3)+pow(c,3)+pow(d,3)){// 如果满足条件,则输出找到的解printf("Cube = %d,Triple = (%d,%d,%d)\n",a,b,c,d);}}}}}return 0; // 主函数返回0,表示程序正常结束
}
/*这个程序的效率并不高,因为它使用了多重嵌套循环进行枚举。对于较大的n值,程序可能需要很长时间才能运行完成。此外,该程序也没有考虑a、b、c、d的顺序问题,即它找到的解可能会包含重复的组合(例如,对于a=27,b=9,c=8,d=1和a=27,b=8,c=9,d=1是同一个解,但程序会输出两次)。如果需要避免这种情况,可以在输出之前添加额外的检查来确保找到的解的唯一性。
*/
二、不定方程求解(20分)
给定正整数a,b,c。求不定方程ax+by=c关于未知数x和y的所有非负整数解组数。
时间限制: 1000ms
内存限制: 65536kb
输入
一行,包含三个正整数a, b,c,两个整数之间用单个空格隔开。每个数均不大于1000。
输出
一个整数,即不定方程的非负整数解组数。
样例输入
2 3 18
样例输出
4
#include<stdio.h> // 引入标准输入输出头文件
#include<math.h> // 引入数学函数头文件int main() {int a,b,c; // 声明三个整数变量a, b, cint x,y,count=0; // 声明两个整数变量x, y,以及一个计数器count并初始化为0scanf("%d %d %d",&a,&b,&c); // 从标准输入读取三个整数值并分别赋值给a, b, c// 枚举所有0到c的数据for(x=0; x<=c; x++){ // 外层循环,x从0遍历到cfor(y=0; y<=c; y++){ // 内层循环,y从0遍历到cif(a*x+b*y==c) // 如果方程a*x + b*y = c成立count++; // 计数器count加1}}printf("%d",count); // 输出计数器的值,即满足方程的整数解的数量return 0; // 程序正常结束,返回0
}
/*这个程序使用了两层嵌套循环来枚举所有可能的 (x, y) 组合,并检查哪些组合满足给定的方程。每找到一个满足条件的组合,计数器 count 就增加1。最后,程序输出 count 的值,即满足方程的整数解的数量。
*/
三、分解因数(20分)
给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3*...*an
,并且1<a1 <= a2<= a3 <= ... <= an
,问这样的分解的种数有多少。注意到a = a也是一种分解。
时间限制: 1000ms
内存限制: 65536kb
输入
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a (1 <a < 32768)
输出
n行,每行输出对应一个输入。输出应是一个正整数,指明满足要求的分解的种数
样例输入
2
2
20
样例输出
1
4
#include<stdio.h> // 引入标准输入输出库int n,ans=0; // 定义全局变量n和ans。n用于存储输入的整数,ans用于存储n的不同正因数的数量,初始化为0// 定义一个递归函数dfs,用于计算n的不同正因数数量
void dfs(int h,int z){if(h==1){ // 如果h为1,则找到一个正因数ans++; // ans加1return; // 返回上一层递归}for(int i=z; i<=h; ++i) // 从z开始到h,遍历所有可能的因数if(h%i==0) // 如果i是h的一个因数dfs(h/i,i); // 递归调用dfs,处理h/i和当前的i
}int main() { // 主函数int T; // 定义变量T,用于存储测试案例的数量scanf("%d",&T); // 从标准输入读取T的值while(T--){ // 对于每一个测试案例scanf("%d" ,&n); // 从标准输入读取n的值ans=0; // 重置ans为0,为下一个测试案例做准备if(n==2){ // 如果n是2printf("1\n"); // 直接输出1,因为2只有一个正因数1(除了它本身)continue; // 跳过当前循环的剩余部分,进入下一个测试案例}dfs(n,2); // 调用dfs函数计算n的不同正因数数量printf("%d\n",ans); // 输出n的不同正因数数量}return 0; // 程序正常结束,返回0
}
/*程序首先读取测试案例的数量T,然后对于每一个测试案例,读取一个整数n,并计算n的不同正因数数量。如果n是2,则直接输出1,因为2只有一个正因数1(除了它本身)。否则,使用递归函数dfs来计算n的不同正因数数量,并输出结果。
*/
四、上台阶(20分)
楼梯有n(100 > n >0)阶台阶,上楼时可以一步上1阶,也可以一步上2阶,也可以一步上3阶,编程计算共有多少种不同的走法。
时间限制: 1000ms
内存限制: 65536kb
输入
输入的每一行包括一组测试数据,即为台阶数n。最后一行为0,表示测试结束。
输出
每一行输出对应一行输入的结果,即为走法的数目。
样例输入
1
2
3
4
0
样例输出
1
2
4
7
// 引入标准输入输出头文件
#include<stdio.h>// 定义一个名为func的函数,它接受一个整数参数x
int func(int x) {// 如果x等于1,函数返回1if(x==1)return 1;// 如果x等于2,函数返回2if(x==2)return 2;// 如果x等于3,函数返回4if(x==3)return 4;// 如果x不是1、2或3,则递归调用func函数,传入x-1、x-2和x-3作为参数,并将结果相加后返回return func(x-1)+func(x-2)+func(x-3);
}// 主函数
int main() {// 定义一个包含100个整数的数组x和一个循环变量iint x[100],i;// 输入数据:循环读取用户输入的整数,存入数组x中,直到用户输入0为止for(i=0; i<100; i++){scanf("%d" ,&x[i]); // 使用scanf函数读取用户输入的整数,并存储到数组x的相应位置if(x[i]==0) // 如果读取到的整数为0,则跳出循环break;}// 计算并打印结果:循环遍历数组x,对于每个非零元素,调用func函数计算其结果,并使用printf函数打印出来for(i=0; i<100; i++){if(x[i]==0) // 如果当前元素为0,则跳出循环break;printf("%d\n",func(x[i])); // 调用func函数计算当前元素的结果,并使用printf函数打印出来}// 主函数返回0,表示程序正常结束return 0;
}
/*需要注意的是,由于func函数是递归的,并且每次调用都会进行三次递归调用,这会导致大量的重复计算。此外,如果输入的数组中包含较大的数字,可能会导致栈溢出或程序运行时间过长。在实际应用中,可能需要使用其他方法来优化这个算法,例如使用动态规划或备忘录技术来避免重复计算。
*/
五、田忌赛马(20分)
在田忌赛马的故事中,孙膑用自己的下等马对战对手的上等马,自己上等马对阵对手的中等马,自己的中等马对阵对手的下等马,从而赢得了胜利。现在即将进行的是N匹马的赛马比赛。双方队伍的马各分为N等。已知只有当我方马的等级比对方马等级高X等以上(包含X)时,我方才可以取得这场比赛的胜利。如果在N场比赛中我方的胜场数大于对方,则我方取得最终的胜利。现在已知对方这N场比赛的出战方案,请计算所有令我方最终获胜的出战方案。
时间限制: 1000ms
内存限制: 65536kb
输入
第一行两个整数,N和X。N≤9,0 ≤X<N。第二行N个正整数,A(1.).…A(N)。A(i)表示第i场比赛对方马的等级,1≤i≤N。等级越高越强
输出
按字典序输出所有我方最终获胜的方案,每个方案一行。每行是N个正整数,第i个数表示我方第i场比赛马的等级。
样例输入
样例1输入
3 1
3 2 1
样例2输入
3 0
3 1 2
样例输出
样例1输出
1 3 2
样例2输出
1 2 3
1 3 2
2 1 3
3 1 2
3 2 1
// 引入标准库头文件,提供基本的数据结构和算法支持
#include<bits/stdc++.h>
#include <iostream>
#include <algorithm>
using namespace std;// 定义全局数组A,用于存储用户输入的数值
int A[12];
// 定义全局变量N, X, xy
int N,X,xy;
// 定义全局数组x,用于生成排列
int x[12];// 定义函数prt,用于检查当前排列是否满足条件并打印满足条件的排列
void prt(int arr[],int end){int i;int sum=0;// 遍历当前排列for(i=0; i<=end; i++)// 如果当前排列的元素大于或等于A[i] + X,则sum加1if(arr[i]>=A[i]+X)sum++;// 如果满足条件的元素数量大于或等于xy,则打印当前排列if(sum>=xy){for(i=0; i<=end; ++i){printf("%d ",arr[i]);}printf("\n");}
}// 定义函数perm,用于生成所有可能的排列
void perm(int arr[],int len){// 如果排列长度小于2,则直接返回if(len<2)return;int i,j,temp;do {// 输出当前排列prt(arr,len-1);i=j=len-1;// 向前查找第一个变小的元素while(i>0 && arr[i]<arr[i-1])--i;temp=i;if(i==0)break;// 向后查找第一个比arr[i-1]大的元素while(temp+1<len && arr[temp+1]>arr[i-1])++temp;swap(arr[i-1],arr[temp]);//交换两个值reverse(arr+i,arr+len);//逆序} while(true);
}// 主函数
int main() {int i,j,k;// 读取用户输入的N和Xscanf("%d%d",&N,&X);// 读取用户输入的数组Afor(i=0; i<N; i++)scanf("%d",&A[i]);// 根据N的奇偶性计算xy的值if(N%2==0)xy=N/2+1;elsexy=(N+1)/2;// 初始化排列数组xfor(i=1; i<=N; i++)x[i]=i;// 调用perm函数生成排列并检查是否满足条件perm(x+1,N);return 0;
}
/*这段代码的目的是生成一个长度为N的排列,使得排列中的每个元素加上对应的A数组中的元素后,至少有xy个元素大于等于X。它通过回溯算法生成所有可能的排列,并使用prt函数来检查每个排列是否满足条件。如果满足条件,就打印出该排列。
*/