2021-2022CSUC语言期末考试二-创新互联

1.格式转换

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名与空间、网络空间、营销软件、网站建设、开鲁网站维护、网站推广。 问题 A: 格式转换(20分)

题目描述

老师知道小南对各个国家和地区的日期和时间表示格式颇有研究,于是给了小南一个任务,将A地的时间点信息(日期表示格式为月/日/年,时间表示格式为24小时制0:0~23:59)转换为B地的时间点信息(日期表示格式为年月日,时间表示格式为12小时制00:00~11:59AM, 00:00~11:59PM)。聪明的你能帮他编写一个程序自动转换吗?

输入

多组样例。每行输入一个样例包括一串整数数据,格式为h:p,m/d/y,其中0≤h≤23,0≤m≤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

#includeint main(void)
{
    int h, p, m, d, y;
    while (~scanf("%d:%d,%d/%d/%d", &h, &p, &m, &d, &y))
    {
        printf("%04d%02d%02d,", y, m, d);
        if (h >= 12)
            printf("%02d:%02dPM\n", (h == 12) ? 0 : h-12, p);
        else
            printf("%02d:%02dAM\n", h, p);
    }
    return 0;
}

2.描绘闪电

问题 B: 描绘闪电(20分)

题目描述

你见过闪电吗?闪电经常以耀眼的姿势一闪而过。夜里,小南走在回宿舍路上,本是宁静的夜色,猛地一道闪电,闪耀而过。回到宿舍,小南突然很想用代码记下闪电的模样,聪明的你能帮帮他吗?

输入

多组样例。每行一个样例包含一个正整数 n,表示闪电的大小(0<n≤100)。

输出

对于每一个输入的n,输出对应一个大小的闪电,闪电由*组成,两个*之间没有空格。每个输出占一行或者多行,并且每一个闪电后有一行空行。具体输出格式请参考样例。

样例输入 Copy

1
2
3

样例输出 Copy

* 
**
* 

  *  
 *  
***
 *  
*  

   *   
  *   
 *   
****
  *   
 *   
*
#includeint main(void)
{
    int n;
    while (~scanf("%d", &n))
    {
        for (int i = 0; i< n; i++)
        {
            for (int j = 1; j<= n - i; j++)
            {
                printf(" ");
            }
            printf("*");
            printf("\n");
        }//打印第一段

        for (int i = 1; i<= n + 1; i++)
            printf("*");
        printf("\n");//打印第二段

        for (int i = 0; i< n; i++)
        {
            for (int j = n - i-1; j >= 1; j--)
                printf(" ");
            printf("*\n");
        }//打印第三段

        printf("\n");
    }
    return 0;
}

拆分成三段来打印

3.密码设置

问题 C: 密码设置(20分)

题目描述

小南有个密码本,详细记录着她在每个网站上的密码,但是有的密码设置可能存在安全问题,她想请聪明的你帮她看看密码设置是否正确。安全密码的判断有以下几个规则:

(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#includeint main(void)
{
	char s[35];
	while (~scanf("%s", s))
	{
		int len = strlen(s), sz = 0, xx = 0, dx = 0, ts = 0, flag = 0,flag2=1;
		if (len< 8)
		{
			printf("no\n");
			continue;
		}
		else//首先需要长度大于等于8,才能继续判断具体字符
		{
			for (int i = 0; i< len; i++)
			{
				int e = 1;//e记录是否有题目范围外的其他字符
					if (s[i] >= '0' && s[i]<= '9')//判断数字
						sz = 1,e=0;
					if (s[i] >= 'a' && s[i]<= 'z')//判断小写字母
						xx = 1,e=0;
					if (s[i] >= 'A' && s[i]<= 'Z')//判断大写字母
						dx = 1,e = 0;
					if (s[i] == '!' || s[i] == '@' || s[i] == '#' || s[i] == '$' || s[i] == '*' || s[i] == '~')//判断特殊字符
						ts = 1, e = 0;
				if (e == 1)
				{
					flag2 = 0;
					printf("no\n");
					break;
				}
			}
			if (flag2)
			{
				flag = sz + xx + dx + ts;
				if (flag >= 3)//判断是否满足要求中至少三项
					printf("yes\n");
				else
					printf("no\n");
			}
		}
	}
	return 0;
}

4.伪素数列

问题 D: 伪素数列(20分)

题目描述

如果一个正整数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
#includeint isprime(int x)
{
	if (x<= 1)
		return 0;
	else
	{
		for (int i = 2; i * i<= x; i++)
		{
			if (x % i == 0)
				return 0;
		}
		return 1;
	}
}
int main(void)
{
	int a[5005] = { 0 };
	int cnt = 0;
	for (int i = 2; cnt<= 5000; i++)
	{
		if (isprime(i))
			a[cnt++] = i;
		else
		{
			int flag = 0;
			int j = i;
			while (j>0&&isprime(j%10))
			{
				j = j / 10;
			}
			if (j == 0)
				a[cnt++] = i;
		}
	}
	
	int x;
	while (~scanf("%d", &x))
	{
		printf("%d\n", a[x - 1]);
	}
	return 0;
}

注意应尽量使代码简洁,不然会增加时间复杂度。

(我写这类题目经常时间超限...)

5.实数相加

问题 E: 实数相加(10分)

题目描述

C语言就要期末考试了,经过一学期的学习,小南学会了分数相加、分数相减、大整数相加,可就是没有尝试过将两个大达400位的实数相加。在调试过程中,小南遇到了很多问题,一直解决不了。你能帮他编写一个程序实现两个实数相加吗?

输入

多组样例。每行输入一个样例包括两个用空格分开的实数xy,其中xy是长度不大于400位的非负实数。注意,非负实数中也可能包括非负整数,正整数会省略小数点和后面的0,只包括整数部分。

输出

对于每一行输入,输出两个实数xy相加的结果。输出结果中整数部分的前面和小数部分的末尾不输出多余的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#includeint main(void)
{
    char x[405] = { 0 }, y[405] = { 0 };
    while (~scanf("%s %s", x, y))//用字符串的方式读入两个实数X和Y
    {
        int l1 = strlen(x), l2 = strlen(y);
        char x1[405] = { 0 }, x2[405] = { 0 };//x1是第一个数的整数部分,x2是第一个数的小数部分
        int i=l1, j=l2;//注意i与j的赋值不能为0,若找不到小数点那么整数部分长度就是l1与l2
        for (int k = 0; k< l1; k++)
        {
            if (x[k] == '.')
            {
                i = k;//找到小数点,就是整数和小数部分分割的位置
            }
        }
        for (int k = 0; k< i; k++)
        {
            x1[k] = x[k];
        }
        for (int k = i + 1; k< l1; k++)
        {
            x2[k-i-1] = x[k];
        }//分割x

        char y1[405] = { 0 }, y2[405] = { 0 };
        for (int k = 0; k< l2; k++)
        {
            if (y[k] == '.')
            {
                j = k;
            }
        }
        for (int k = 0; k< j; k++)
        {
            y1[k] = y[k];
        }
        for (int k = j + 1; k< l2; k++)
        {
            y2[k - j - 1] = y[k];
        }//分割y

        int r1[405] = { 0 }, t=0;//r1为储存整数最终结果的数组
        int p = i - 1, q = j - 1;
        

        int r2[405] = { 0 }, t2 = 0;//r2为储存小数最终结果的数组
//因为最终小数部分相加后可能会向整数部分进位,所以先计算小数部分
        int len;
        if (l1 - i >l2 - j)//len的长度应为两者中较长者
            len = l1 - 1 - i-1;
        else
            len = l2 - 1 - j-1;
        while (len >= 0)
        {
            int g=x2[len], r=y2[len];

//因为数组中原本储存的是数字0,所以此处应将其转换为字符0才能进行下面的转换
            if (x2[len] == 0)
                g = '0';
            if (y2[len] == 0)
                r = '0';

            r2[t2] = r2[t2]+g - '0' + r - '0';
            if (r2[t2] >= 10)
            {
                r2[t2] %= 10;
                r2[t2 + 1]++;
            }
            t2++,len--;
        }

        if (r2[t2] != 0)//向整数部分进位
        {
            r1[0] = r1[0] + 1;
        }
        
        while (p >= 0 && q >= 0)
        {
            r1[t] = r1[t] + x1[p] - '0' + y1[q] - '0';
            if (r1[t] >= 10)
            {
                r1[t] = r1[t] % 10;
                r1[t + 1]++;
            }
            t++, p--, q--;
        }

//计算多出来的部分
        while (p >= 0)
        {
            r1[t] = r1[t] + x1[p] - '0';
            t++, p--;
        }
        while (q >= 0)
        {
            r1[t] = r1[t] + y1[q] - '0';
            t++, q--;
        }//至此整数部分加好
        
        if (r1[t] == 0)//判断整数部分的长度
            t = t - 1;

        for (t; t >= 0; t--)
            printf("%d", r1[t]);//输出整数部分
        
        int fir = 0;
        while (r2[fir] == 0&&fir= fir; j--)
                printf("%d", r2[j]);
        }
        printf("\n");
    }
    return 0;
}

6.谍影寻踪

问题 F: 谍影寻踪(10分)

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

输入

多组样例。每组样例包括多行输入,第一行包含一个正整数n(0<n≤1000),表示截获到的情报数。接下来的n行输入形式为A->B,表示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

本题思路:指针的基本操作(前插、后插)+结构体

当时写这题的时候没有注意到可能两个人都是曾经出现过的,所以后面的判断重合部分又加了che指针检查是否两者都是出现过的,幸好最后没有时间超限,不知道能不能有大佬提供更简单的解法。

#include#include#includeint main(void)
{
	int n;
	while (~scanf("%d", &n))
	{
		struct node
		{
			int num;
			int cnt = 1;
			int n1;
			int n2;
			struct node* next;
		};

		struct node* head = NULL;
		struct node* A = (struct node*)malloc(sizeof(struct node));
		struct node* B = (struct node*)malloc(sizeof(struct node));
		scanf("%d,%d->%d,%d", &(A->num), &(A->n1), &(B->num), &(B->n1));
		B->next = head;
		A->next = B;
		head = A;
		for (int i = 1; i<= n - 1; i++)
		{
			A = (struct node*)malloc(sizeof(struct node));
			B = (struct node*)malloc(sizeof(struct node));
			scanf("%d,%d->%d,%d", &(A->num), &(A->n1), &(B->num), &(B->n1));
			B->next = NULL;
			A->next = B;
			struct node * cur = head,*pre=NULL;
			while ((cur->num) != A->num && (cur->num) != B->num)
				pre = cur, cur = cur->next;
			if (cur->num == A->num)
			{
				int flag = 1;
				struct node* che = head;
				for (; che->next != NULL; che = che->next)
				{
					
					if (che->num == B->num)
					{
						
						flag = 0;
						break;
					}
				}
				if (che->num == B->num)
				{

					flag = 0;
					
				}
				if (flag)
				{
					B->next = cur->next;
					cur->next = B;
				}
				else
				{
					if (che->n1 != B->n1)
					{
						che->cnt = 2;
						che->n2 = B->n1;
					}
				}
				if (cur->n1 != A->n1)
				{
					cur->cnt = 2;
					cur->n2 = A->n1;
				}
			}
			if (cur->num == B->num)
			{
				int flag = 1;
				struct node* che = head;
				for (; che->next != NULL; che = che->next)
				{
					if (che->num == A->num)
					{
						flag = 0;
						break;
					}
				}
				if (che->num == A->num)
				{
					flag = 0;
				}
				if (flag)
				{
					if (cur == head)
					{
						A->next = cur;
						head = A;
					}
					else
					{
						pre->next = A;
						A->next = cur;
					}
				}
				else
				{
					if (che->n1 != A->n1)
					{
						che->cnt = 2;
						che->n2 = A->n1;
					}
				}
				if (cur->n1 != B->n1)
				{
					cur->cnt = 2;
					cur->n2 = B->n1;
				}
			}
		}
		struct node* p = head;
		while (p->next != NULL)
		{
			if (p->cnt == 2)
			{
				printf("%d,%d#%d->", p->num, p->n1, p->n2);
			}
			else
			{
				printf("%d,%d->", p->num, p->n1);
			}
			p = p->next;
		}
		if (p->cnt == 2)
		{
			printf("%d,%d#%d", p->num, p->n1, p->n2);
		}
		else
		{
			printf("%d,%d", p->num, p->n1);
		}
		printf("\n");
	}
	return 0;
}

以上仅个人的一点浅薄的看法,这是一学期来第一次考试满分,希望能对大家有帮助。如果有更好的解法,欢迎批评指正。

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


文章名称:2021-2022CSUC语言期末考试二-创新互联
URL链接:http://scyanting.com/article/ddihpp.html