中南大学(CSU)2021级期末考试

文章目录

  • 21级期末机试-描绘闪电(20分)
  • 21级期末机试-密码设置(20分)
  • 21级期末机试-实数相加(10分)
  • 21级期末机试-伪素数列(20分)
  • 21级期末机试-格式转换(20分)
  • 21级期末机试-谍影寻踪(10分)

21级期末机试-描绘闪电(20分)

[命题人 : 外部导入]
时间限制 : 1.000 sec 内存限制 : 128 MB

题目描述
你见过闪电吗?闪电经常以耀眼的姿势一闪而过。夜里,小南走在回宿舍路上,本是宁静的夜色,猛地一道闪电,闪耀而过。回到宿舍,小南突然很想用代码记下闪电的模样,聪明的你能帮帮他吗?
输入
多组样例。每行一个样例包含一个正整数 n,表示闪电的大小(0 输出
对于每一个输入的n,输出对应一个大小的闪电,闪电由组成,两个之间没有空格。每个输出占一行或者多行,并且每一个闪电后有一行空行。具体输出格式请参考样例。

样例输入 Copy
1
2
3
样例输出 Copy
 * 
**
* 

  *  
 *  
***
 *  
*  

   *   
  *   
 *   
****
  *   
 *   
*   
#include
int main()
{
	int n;
	while (~scanf("%d", &n))
	{
		n++;
		for (int i = n - 1; i >= 1; i--)
		{
			for (int kongge = 1; kongge <= i; kongge++)
			{
				printf(" ");
			}
			printf("*\n");
		}
		for (int i = 1; i <= n; i++)
		{
			printf("*");
		}
		printf("\n");
		for (int i = n - 1; i >= 1; i--)
		{
			for (int kongge = 1; kongge < i; kongge++)
			{
				printf(" ");
			}
			printf("*\n");
		}
		printf("\n");
	}
	return 0;
}

21级期末机试-密码设置(20分)

[命题人 : 外部导入]
时间限制 : 1.000 sec 内存限制 : 128 MB

题目描述
小南有个密码本,详细记录着她在每个网站上的密码,但是有的密码设置可能存在安全问题,她想请聪明的你帮她看看密码设置是否正确。安全密码的判断有以下几个规则:
(1)密码长度必须≥8
(2)包含数字
(3)包含大写字母
(4)包含小写字母
(5)至少包含6个特殊字符(! @ # $ * ~)中的一个
以上规则,除(1)必须满足外,其他四个条件至少满足其中三个才是安全的密码。
输入
多组样例。每行一个样例,输入一个字符串S代表密码,字符串S的长度len(S)满足:1≤len(S)≤30,且只包含密码设置要求的数字、字母和特殊字符,无其他非法字符。
输出
对于每一组样例,输出一个判断结果。如果满足安全密码的设置要求则输出yes,不满足则输出no。每个输出占一行。
样例输入 Copy
ttttttttt
123Aa~
123456QqWe
aQwe!1234
123$#abc
样例输出 Copy
no
no
yes
yes
yes

#include
#include
int main(void)
{
	char arr[31] = { 0 };
	while (~scanf("%s", &arr))
	{
		int sum = 0;
		int flag1 = 0, flag2 = 0, flag3 = 0, flag4 = 0;
		int n = strlen(arr);
		if (n >= 8)
		{
			for (int i = 0; i < n; i++)
			{
				if (arr[i] >= '1' && arr[i] <= '9')
					flag1 = 1;
				else if (arr[i] >= 'A' && arr[i] <= 'Z')
					flag2 = 1;
				else if (arr[i] >= 'a' && arr[i] <= 'z')
					flag3 = 1;
				else if (arr[i] == '!' || arr[i] == '@' || arr[i] == '#' || arr[i] == '$' || arr[i] == '*' || arr[i] == '~')
					flag4 = 1;
			}
			if (flag1 == 1)sum++;
			if (flag2 == 1)sum++;
			if (flag3 == 1)sum++;
			if (flag4 == 1)sum++;
			if (sum >= 3)
			{
				printf("yes\n");
			}
			else
			{
				printf("no\n");
			}
		}
		else
		{
			printf("no\n");
		}
	}
	return 0;
}

21级期末机试-实数相加(10分)

[命题人 : 外部导入]
时间限制 : 1.000 sec 内存限制 : 128 MB

题目描述
C语言就要期末考试了,经过一学期的学习,小南学会了分数相加、分数相减、大整数相加,可就是没有尝试过将两个最大达400位的实数相加。在调试过程中,小南遇到了很多问题,一直解决不了。你能帮他编写一个程序实现两个实数相加吗?
输入
多组样例。每行输入一个样例包括两个用空格分开的实数x和y,其中x和y是长度不大于400位的非负实数。注意,非负实数中也可能包括非负整数,正整数会省略小数点和后面的0,只包括整数部分。
输出
对于每一行输入,输出两个实数x和y相加的结果。输出结果中整数部分的前面和小数部分的末尾不输出多余的0;如果是整数,不输出小数点和小数点后面的0。每个输出占一行。
样例输入 Copy
1.1 2.9
1.1111111111 2.3444323343
1 1.1
1.1111 1.1889
样例输出 Copy
4
3.4555434454
2.1
2.3

#include
#include
#define count(xLength,xzheng,x,xxiao) \
 for (int i = 0; i < xLength; i++)\
{\
	if (x[i] != '.')\
		xzheng++;\
	else\
	{\
		xxiao = xLength - xzheng - 1;break;\
	}\
		}
#define MAX(x,y) x>y?x:y

void fuxiaoshu(char* x, int xzheng, char* xnew, int xxiao)
{
	while (*xnew != 0) xnew++;
	for (int i = xzheng +1;i < xzheng + 1 + xxiao; i++)
	{
		*xnew = x[i];
		xnew++;
	}
}
int main(void)
{
	char x[410] = { 0 };
	char y[410] = { 0 };
	while (~scanf("%s %s", x, y))
	{

		int xLength = strlen(x), xzheng = 0, xxiao = 0;
		int yLength = strlen(y), yzheng = 0, yxiao = 0;
		count(xLength, xzheng, x, xxiao);
		count(yLength, yzheng, y, yxiao);
		int mzheng = MAX(xLength, yLength);
		char xnew[900] = { 0 }, ynew[900] = { 0 };
		if (xzheng >= yzheng)
		{
			strncpy(xnew, x,xzheng);
			for (int i = 0; i < xzheng - yzheng; i++)
			{
				ynew[i] = '0';
			}
			strcat(ynew, y);
			for (int i = xzheng; i < yLength+xzheng; i++)
			{
				ynew[i] = 0;
			}
		}
		else
		{
			strncpy(ynew, y,yzheng);
			for (int i = 0; i < yzheng - xzheng; i++)
			{
				xnew[i] = '0';
			}
			strcat(xnew, x);
			for (int i = yzheng; i <yLength+yzheng; i++)
			{
				xnew[i] = 0;
			}
		}
		mzheng = (MAX(xzheng, yzheng)) + (MAX(xxiao, yxiao))+1;
		fuxiaoshu(x, xzheng, xnew, xxiao);
		fuxiaoshu(y, yzheng, ynew, yxiao);
		char arr[900] = { 0 };
			for (int i = mzheng-2; i>=1;i--)
			{
				if (xnew[i] == 0)
					xnew[i] = '0';
				if (ynew[i] ==0 )
					ynew[i] = '0';
				arr[i] += xnew[i] - '0' + ynew[i] - '0'+'0';
				if (arr[i] -'0' >= 10)
				{
					arr[i] -= 10;
					arr[i - 1]++;
				}
			}
			arr[0] += xnew[0] - '0' + ynew[0] - '0';
			printf("%d", arr[0]);
			arr[0] += '0';
			for (int i = 1; i < (MAX(xzheng, yzheng)); i++)
			{
				printf("%c", arr[i]);
			}
			int nn = strlen(arr)-1;
			while (arr[nn] == '0'&&nn>= (MAX(xzheng, yzheng)))
			{
				arr[nn] = 0;
				nn--;
			}
			if (nn+1 > (MAX(xzheng, yzheng)))
			{
				printf(".%s\n", arr + (MAX(xzheng, yzheng)));
			}
			else
			{
				printf("\n");
			}
	}
	return 0;
}

我的思路是把整数和小数的小数点去掉,当作一个大的字符串相加。给少的前面补齐0,后面补齐0.
还有一种思路是分开算,将整数和小数。
犯的错误:数组开的小了

21级期末机试-伪素数列(20分)

[命题人 : 外部导入]
时间限制 : 1.000 sec 内存限制 : 128 MB

题目描述
如果一个正整数A是素数,或者A的每一位数字都是素数,我们称A为伪素数。例如,23是素数,235的每一位数字都是素数,所以23和235都是伪素数,而135不是素数,其中的数字1不是素数,所以135不是伪素数。老师给了小南一个任务,让他在一个称作伪素数列的集合An={2,3,5,7,11,13,17,19,22,23,25,…}中快速找到第k个伪素数,聪明的你能帮他完成任务吗?
输入
多组样例。每行输入一个样例包括一个正整数k(1≤k≤5000)。
输出
对每一个输入的k,输出一个正整数x,表示数列An中的第k项的值,其值范围不会超过int型。每个输出占一行。
样例输入 Copy
1
5
10
样例输出 Copy
2
11
23

#include
int sushu(int m)
{
	if (m == 1)
		return 0;
	if (m == 0)
		return 0;
	for (int i = 2; i <= sqrt(m); i++)
	{
		if (m % i == 0)
			return 0;
	}
	return 1;
}

#include
int main(void)
{
	int b = sushu(12);
	int shulie[100000] = { 0 },sum=0,flag2;
	for (int i = 2; sum <= 5000; i++)
	{
		flag2 = 1;
		int icopy = i;
		while (icopy)
		{
			if ((sushu(icopy%10)) == 0)
			{
				flag2 = 0;
				break;
			}
			icopy /= 10;
		}
		if (sushu(i) || flag2)
		{
			sum++;
			shulie[sum] = i;
		}
	}
	int k;
	while (~scanf("%d", &k))
	{
		printf("%d\n", shulie[k]);
	}
	return 0;
}

注意理解题意。题目中说不是素数。那么1和0虽然既不是素数也不是合数,但是确实不是素数,所用sushu这一函数应该考虑

21级期末机试-格式转换(20分)

[命题人 : 外部导入]
时间限制 : 1.000 sec 内存限制 : 128 MB

题目描述
老师知道小南对各个国家和地区的日期和时间表示格式颇有研究,于是给了小南一个任务,将A地的时间点信息(日期表示格式为月/日/年,时间表示格式为24小时制0:023:59)转换为B地的时间点信息(日期表示格式为年月日,时间表示格式为12小时制00:0011:59AM, 00:00~11:59PM)。聪明的你能帮他编写一个程序自动转换吗?
输入
多组样例。每行输入一个样例包括一串整数数据,格式为h:p,m/d/y,其中0≤h≤23,0≤p≤59,1≤m≤12,1≤d≤31,1900≤y≤2200)。
输出
对于每一个输入,按照要求输出转换后的结果。每个输出占一行。
样例输入 Copy
23:11,2/17/2011
6:6,10/1/2021
12:0,1/2/2022
样例输出 Copy
20110217,11:11PM
20211001,06:06AM
20220102,00:00PM

#include
#define TIME(a)  (a>=12?'P':'A')
int main()
{
	int h, p, m, d, y;
	while (~scanf("%d:%d,%d/%d/%d",&h,&p,&m,&d,&y))
	{
		char time = TIME(h);
		h %= 12;
		printf("%d%.2d%.2d,%.2d:%.2d%cM\n", y, m, d, h, p,time);
	}
}

21级期末机试-谍影寻踪(10分)

[命题人 : 外部导入]
时间限制 : 1.000 sec 内存限制 : 128 MB

题目描述

2020年10月,国家安全机关组织实施“迅雷-2020”专项行动,破获数百起间谍窃密事件,有效维护了国家安全和利益。在行动中,我方安全机关破获了一个情报组织,他们是单线联系的。我方给情报组织中的每个人员一个唯一的代号。同时,情报人员为了隐秘,可能会有不同的姓名编号(设定最多两个姓名编号)。我方顺藤摸瓜,分别截获并返回组织信息。请你帮忙汇总并恢复这条组织链条。

输入

多组样例。每组样例包括多行输入,第一行包含一个正整数n(0B,表示A单向联系B,B是A的下线。A和B表示两名组织人员的信息,包括代号x和姓名编号y,用逗号“,”分开。代号x和姓名编号y为整数,满足1≤x,y≤999999。除了第一行,A或B的代号信息在之前的行中出现过。

输出

对于每一组样例,按照顺序在一行中输出该组织的所有成员的信息,用“->”间隔。每个输出占一行。如果有一个代号有两个姓名编号,则认为是一个成员,输出代号和对应的两个姓名编号,用“#”分开。如有两个信息1,2345和1,6666,输出时对应一个成员信息1,2345#6666,两个姓名编号先输入的在前面。

样例输入 Copy
3
1,1234->5,2236
5,2236->3,7177
7,3234->1,1234
4
1,258->10,111111
5,4353->1,36900
7,22->5,4353
10,159->20,220102
2
1,111->2,222
1,101->2,202
样例输出 Copy
7,3234->1,1234->5,2236->3,7177
7,22->5,4353->1,258#36900->10,111111#159->20,220102
1,111#101->2,222#202


#include
#include
struct node {
	int daihao;
	int xingming[2] ;
	struct node* next;
};
struct node* add_to_list( int daihao, int xingming)
{
	struct node* newnode = (struct node*)calloc(1,sizeof(struct node));
	newnode->daihao = daihao;
	newnode->xingming[0] = xingming;
	return newnode;
}
struct node* search_list(struct node* list, int daihao)
{
	while (list->daihao != daihao)
	{
		list = list->next;
	}
	return list;
}
int main(void)
{
	int n;
	while (~scanf("%d",&n))
	{
		struct node* first = { 0 }, *end = { 0 };
		int daihao1, xingming1, daihao2, xingming2;
		scanf("%d,%d->%d,%d", &daihao1, &xingming1, &daihao2, &xingming2);
		first = add_to_list(daihao1, xingming1);
		end= add_to_list(daihao2, xingming2);
		first->next = end;
		n--;
		while (n--)
		{
			scanf("%d,%d->%d,%d", &daihao1, &xingming1, &daihao2, &xingming2);
			if (daihao2 == first->daihao)
			{
				if (xingming2 == first->xingming[0]);
				else
				{
					first->xingming[1] = xingming2;
				}

				struct node* p=add_to_list(daihao1, xingming1);
				 p->next=first;
				 first = p;
			}
			else if(daihao1==end->daihao)
			{
				if (xingming1 == end->xingming[0]);
				else
				{
					end->xingming[1] = xingming1;
				}
				(end->next) = add_to_list(daihao2, xingming2);
				end = end->next;
			}
			else
			{
				struct node* p =search_list(first, daihao1);
				if (p->xingming[0] == xingming1);
				else
					p->xingming[1] = xingming1;
				p = p->next;
				if (p->xingming[0] == xingming2);
				else
					p->xingming[1] = xingming2;
			}
		}
				for (; ; first = first->next)
		{
			printf("%d,%d", first->daihao, first->xingming[0]);
			
				if (first->xingming[1] != 0)
				{
					printf("#%d", first->xingming[1]);
				}
			if(first!=end)
			printf("->");
			else
			{
				break;
			}
		}
		
		printf("\n");

	}
	return 0;
}

思路
calloc分配内存会置0;
链表。
前插与后插。
注意可能犯错的地方是,如果名字前面出现了(利用xingming【0】初始化为0,如果ta为0就表明还没有被给xingming过。),新出现的这个不一定是新名字,还需要判断这个名字是否和原来的名字一样。如果一样的话,则不需在更新xingming【1】。

你可能感兴趣的:(CSU,c语言)