2020年HZNU天梯训练赛 Round 1

2020年HZNU天梯训练赛 Round 1

时间:2020.7.14 33

完成情况:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

√ 当场做出来 ※补题补出来 ✘没有补出来

7-1 打印沙漏 (20分)

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

*****
 ***
  *
 ***
*****

所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。

给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。

输入格式:

输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。

输出格式:

首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。

输入样例:
19 *
输出样例:
*****
 ***
  *
 ***
*****
2

代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB

…………………………………………………………………………………………………………

这道题在实现一般打印形状的 基础上多一个对数量的判断——要用掉尽可能多的符号

首先通过找规律发现层数与符号总个数的关系:sum[i+1]=sum[i]+2(2(i+1)-1)

借此先用一个while循环找出对于当前N,所对应的最大层数。

然后就是实现图形的打印。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
	int n,i=1,j,k,sum=1,ans;
	char c;
	cin>>n>>c;
	while(sum<=n)//算出层数 
	{
		sum+=2*(2*(i+1)-1);
		if(sum<=n)i++;
	}
	for(k=0;k<i;k++)//上半个(包括中间行)
	{
		for(j=0;j<k;j++)cout<<" ";
		for(j=0;j<2*(i-k)-1;j++)cout<<c;
		cout<<endl;
	}
	for(k=2;k<=i;k++)//下半个(去掉中间行) 注意对应关系 从2开始方便些
	{
		for(j=0;j<i-k;j++)cout<<" ";
		for(j=0;j<2*k-1;j++)cout<<c;
		cout<<endl;
	}
	ans=n-(sum-2*(2*(i+1)-1));//因为刚才在上面多加了一遍
	cout<<ans;
	return 0;
}

7-2 Hello World! (5分)

本题要求编写程序,输出一个短句“Hello World!”。

输入格式:

本题目没有输入。

输出格式:

在一行中输出短句“Hello World!”。

Hello World!

7-3 计算摄氏温度 (5分)

本题要求编写程序,计算华氏温度100°F对应的摄氏温度。计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型。

输入格式:

本题目没有输入。

输出格式:

按照下列格式输出

fahr = 100, celsius = 计算所得摄氏温度的整数值

算就完事。

#include<iostream>
#include<cmath>
using namespace std;
int main(){
	int c,f;
	f=100;
	cout<<"fahr = "<<f<<", ";
	cout<<"celsius = " <<5*(f-32)/9<<endl;	 
	return 0;
}

7-4 求整数段和 (15分)

给定两个整数AB,输出从AB的所有整数以及这些数的和。

输入格式:

输入在一行中给出2个整数AB,其中−100≤AB≤100,其间以空格分隔。

输出格式:

首先顺序输出从AB的所有整数,每5个数字占一行,每个数字占5个字符宽度,向右对齐。最后在一行中按Sum = X的格式输出全部数字的和X

输入样例:
-3 8
输出样例:
   -3   -2   -1    0    1
    2    3    4    5    6
    7    8
Sum = 30

代码长度限制 16 KB 时间限制 400 ms 内存限制 4 MB

………………………………………………………………………………………………

这道题做的时候卡了一会儿。也挺无语的。

这个主要的问题就是右对齐的5个字符宽度输出。我还想过用for循环来控制但是忘记了printf里面有一个自动控制输出位数的方法。简直了。。。

然后虽然实现了还是有点啰嗦 又写了一版简化版的在注释里,可直接替换//和//之间的内容

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
	int a,b,cnt=1,sum=0;
	cin>>a>>b;
	//
	for(int i=a;i<b;i++)
	{
		if(cnt<5)
		{
			if(i<0){printf("%5d",i);cnt++;}
			else {printf("%5d",i);cnt++;}
		}
		else
		{
			if(i<0){printf("%5d\n",i);cnt=1;}
			else {printf("%5d\n",i);cnt=1;}
		}
		sum+=i;
	} 
	if(b<0){printf("%5d\n",b);sum+=b;}
	else {printf("%5d\n",b);sum+=b;}
	//
	cout<<"Sum = "<<sum;
	return 0;

}
/* for(i=a;i<=b;i++){        //i用来记录输出数字 
    	sum+=i;
    	cnt++;       
    	printf("%5d",i);     //输出5个字符 
    	if(cnt%5 == 0 && i!=b){   //当计数达到5个的时候,就换行 
    		printf("\n");	//把i=b时排除 为了避免最后输出两个换行
		}
	}
	printf("\n");  
*/

7-5 念数字 (15分)

输入一个整数,输出每个数字对应的拼音。当整数为负数时,先输出fu字。十个数字对应的拼音如下:

0: ling 
1: yi
2: er
3: san
4: si
5: wu
6: liu
7: qi
8: ba
9: jiu
输入格式:

输入在一行中给出一个整数,如:1234

提示:整数包括负数、零和正数。

输出格式:

在一行中输出这个整数对应的拼音,每个数字的拼音之间用空格分开,行末没有最后的空格。如 yi er san si

输入样例:
-600

输出样例:

fu liu ling ling

代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB

………………………………………………………………………………………………

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int main ()
{
	char s[10005];
	int i;
	cin>>s;
	for(i=0;i<strlen(s)-1;i++)
	{
		if(s[i]=='-')cout<<"fu ";
		if(s[i]=='0')cout<<"ling ";
		if(s[i]=='1')cout<<"yi ";
		if(s[i]=='2')cout<<"er ";
		if(s[i]=='3')cout<<"san ";
		if(s[i]=='4')cout<<"si ";
		if(s[i]=='5')cout<<"wu ";
		if(s[i]=='6')cout<<"liu ";
		if(s[i]=='7')cout<<"qi ";
		if(s[i]=='8')cout<<"ba ";
		if(s[i]=='9')cout<<"jiu ";
	}
	if(s[i]=='-')cout<<"fu";
	if(s[i]=='0')cout<<"ling";
	if(s[i]=='1')cout<<"yi";
	if(s[i]=='2')cout<<"er";
	if(s[i]=='3')cout<<"san";
	if(s[i]=='4')cout<<"si";
	if(s[i]=='5')cout<<"wu";
	if(s[i]=='6')cout<<"liu";
	if(s[i]=='7')cout<<"qi";
	if(s[i]=='8')cout<<"ba";
	if(s[i]=='9')cout<<"jiu";
	return 0;
 } 

然后发现我写的好啰嗦哦 那就改一改 (果然我是啰嗦大王

#include<iostream>
#include<cstring>
using namespace std;
int main ()
{
	char s[10005];
	int i;
	cin>>s;
	for(i=0;i<strlen(s);i++)
	{
		if(s[i]=='-')cout<<"fu";
		if(s[i]=='0')cout<<"ling";
		if(s[i]=='1')cout<<"yi";
		if(s[i]=='2')cout<<"er";
		if(s[i]=='3')cout<<"san";
		if(s[i]=='4')cout<<"si";
		if(s[i]=='5')cout<<"wu";
		if(s[i]=='6')cout<<"liu";
		if(s[i]=='7')cout<<"qi";
		if(s[i]=='8')cout<<"ba";
		if(s[i]=='9')cout<<"jiu";
		if(i!=strlen(s)-1)cout<<" ";
	}
	return 0;
 } 

7-6 城市间紧急救援 (25分)

作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。

输入格式:

输入第一行给出4个正整数NMSD,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0 ~ (N−1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。

第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。

输出格式:

第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从SD的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。

输入样例:
4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2
输出样例:
2 60
0 1 3

代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB

……………………………………………………………………………………………………………

看到题目知道是最短路问题,但是做的时候还没复习到这个知识就没做。。

等待补题ing。。。。。

7-7 个位数统计 (15分)

给定一个 k 位整数 N=d**k−110k−1+⋯+d1101+d0 (0≤d**i≤9, i=0,⋯,k−1, d**k−1>0),请编写程序统计每种不同的个位数字出现的次数。例如:给定 N=100311,则有 2 个 0,3 个 1,和 1 个 3。

输入格式:

每个输入包含 1 个测试用例,即一个不超过 1000 位的正整数 N

输出格式:

N 中每一种不同的个位数字,以 D:M 的格式在一行中输出该位数字 D 及其在 N 中出现的次数 M。要求按 D 的升序输出。

输入样例:
100311
输出样例:
0:2
1:3
3:1
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
	char s[1010];
	cin>>s;
	int sum[100]= {0};
	for(int i=0;i<strlen(s);i++)
		sum[s[i]-'0']++;
	for(int i=0;i<10;i++)
		if(sum[i]!=0)
			printf("%d:%d\n",i,sum[i]);
	return 0;
}

7-8 考试座位号 (15分)

每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位。正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考试座位就座。但有些考生迟到了,试机已经结束,他们只能拿着领到的试机座位号码求助于你,从后台查出他们的考试座位号码。

输入格式:

输入第一行给出一个正整数 N(≤1000),随后 N 行,每行给出一个考生的信息:准考证号 试机座位号 考试座位号。其中准考证号由 16 位数字组成,座位从 1 到 N 编号。输入保证每个人的准考证号都不同,并且任何时候都不会把两个人分配到同一个座位上。

考生信息之后,给出一个正整数 M(≤N),随后一行中给出 M 个待查询的试机座位号码,以空格分隔。

输出格式:

对应每个需要查询的试机座位号码,在一行中输出对应考生的准考证号和考试座位号码,中间用 1 个空格分隔。

输入样例:
4
3310120150912233 2 4
3310120150912119 4 1
3310120150912126 1 3
3310120150912002 3 2
2
3 4
输出样例:
3310120150912002 2
3310120150912119 1
#include<iostream>
#include<cmath>
using namespace std;
const int maxn=1e3+5;
int a[maxn],b[maxn],c[1003];
char s[1003][16];
int main(){
	int n,m;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		scanf("%s",s[i]);
		cin>>a[i]>>b[i];
		//printf("%s %d\n",s[i],b[i]);
	}
	cin>>m;
	for(int k=0;k<m;k++){scanf("%d",&c[k]);}
	for(int i=0;i<m;++i)
		for(int j=0;j<n;++j)
			if(c[i]==a[j])
			{for(int l=0;l<16;l++)printf("%c",s[j][l]);
			//printf("%s",s[j]);
			 printf(" %d\n",b[j]);break;}	
	return 0;
}

7-9 连续因子 (20分)

一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3×5×6×7,其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。

输入格式:

输入在一行中给出一个正整数 N(1<N<231)。

输出格式:

首先在第 1 行输出最长连续因子的个数;然后在第 2 行中按 因子1*因子2*……*因子k 的格式输出最小的连续因子序列,其中因子按递增顺序输出,1 不算在内。

输入样例:
630
输出样例:
3
5*6*7

这个借助于前几天刚学到的//最长连续因子数的简便求法🙏

质数非质数分开输出即可🙏

typedef long long LL;
using namespace std;
const int maxn=2e5+5;
const int inf = 0x3f3f3f3f;
LL judge(LL n,LL x,LL cnt){
	if(n%x==0) return judge(n/x,x+1,cnt+1);
	else return cnt;
}//最长连续因子数
int main()
{
	LL n,cnt=0,x=0,l;
	cin>>n;
	for(LL i=2;i<sqrt(n);i++)
	{
		if(n%i==0)
		{
			l=judge(n/i,i+1,1);
			if(l>cnt){x=i;cnt=l;}
		}
	}//最小连续因子序列 
	if(cnt==0)	cout<<"1"<<endl<<n<<endl;//质数就直接输出
	else
	{
		cout<<cnt<<endl;
		for(LL i=0;i<cnt;i++)
		{
			if(i!=cnt-1) cout<<x+i<<"*";
			else cout<<x+cnt-1<<endl;
		}
	}
	return 0;
}

7-10 月饼 (25分)

月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。

注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有 3 种月饼,其库存量分别为 18、15、10 万吨,总售价分别为 75、72、45 亿元。如果市场的最大需求量只有 20 万吨,那么我们最大收益策略应该是卖出全部 15 万吨第 2 种月饼、以及 5 万吨第 3 种月饼,获得 72 + 45/2 = 94.5(亿元)。

输入格式:

每个输入包含一个测试用例。每个测试用例先给出一个不超过 1000 的正整数 N 表示月饼的种类数、以及不超过 500(以万吨为单位)的正整数 D 表示市场最大需求量。随后一行给出 N 个正数表示每种月饼的库存量(以万吨为单位);最后一行给出 N 个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。

输出格式:

对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后 2 位。

输入样例:
3 20
18 15 10
75 72 45
输出样例:
94.50

做这道题的时候费了挺大劲,首先感谢做的前一天复习了背包问题和贪心问题,这道题就变成了上述两个问题的拼接体。

首先是贪心部分,我们要让收益尽可能地大,就是要尽可能选用均价最高的月饼,又因为每个月饼有两个相关数值,一开始想到用结构体,但是结构体排序是真滴麻烦,就搞搞pair,可以使用sort排序,这个也是在贪心问题里学到的。这里注意要将pair中first和second倒过来存,这样排序的时候会以均价为排序的优先依据。

然后下面的那个for循环就来自于背包问题。每次比较所剩余量与下一种月饼的重量,选取较小的一个,严格控制边界。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+5 ;
pair<double,double>w[maxn];
int n;
double d;
double ans=0;
//struct node{int x,y;};
int main()
{
	cin>>n>>d;
	for(int i=0;i<n;i++)cin>>w[i].second;//倒过来存便于排序 
	for(int i=0;i<n;i++){cin>>w[i].first;w[i].first/=w[i].second;}
	sort(w,w+n);
	for(int i=n-1;i>=0;i--)
	{
		double t=min(d,w[i].second);
		d-=t;
		ans+=t*w[i].first;
	}
	printf("%.2lf\n",ans);
 } 

7-11 链表去重 (25分)

给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。

输入格式:

输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤105,为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL 用 -1 来表示。

随后 N 行,每行按以下格式描述一个结点:

地址 键值 下一个结点

其中地址是该结点的地址,键值是绝对值不超过104的整数,下一个结点是下个结点的地址。

输出格式:

首先输出去重后的链表,然后输出被删除的链表。每个结点占一行,按输入的格式输出。

输入样例:
00100 5
99999 -7 87654
23854 -15 00000
87654 15 -1
00000 -15 99999
00100 21 23854
输出样例:
00100 21 23854
23854 -15 99999
99999 -7 -1
00000 -15 87654
87654 15 -1

代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
//边读边存 
struct Node{
	int ad,key,next,num;
};
Node node[maxn];
bool vis[maxn];
bool cmp(Node a,Node b)//结构体简便排序
{
	return a.num<b.num;
}
int main ()
{
	int head,n,k1=0,k2=0,x;
	cin>>head>>n;
	for(int i=0;i<maxn;i++)
	{
		node[i].num=2*maxn;
	}
	for(int i=0;i<n;i++)
	{
		cin>>x;
		node[x].ad=x;
		cin>>node[x].key>>node[x].next;
	}
	  for(int i=head;i!=-1;i=node[i].next){
        if(!vis[abs(node[i].key)]){
            vis[abs(node[i].key)]=true;
            node[i].num=k1;
            k1++;
        }else{
            node[i].num=maxn+k2;
            k2++;
        }
    }
    sort(node,node+maxn,cmp);
	int len=k1+k2;
	for(int i=0;i<len;i++)
	{
		if(i!=len-1&&i!=k1-1)
			printf("%05d %d %05d\n",node[i].ad,node[i].key,node[i+1].ad);
		else
				printf("%05d %d -1\n",node[i].ad,node[i].key,node[i+1].ad);
	}
	return 0;
} 

7-12 搜索树判断 (25分)

对于二叉搜索树,我们规定任一结点的左子树仅包含严格小于该结点的键值,而其右子树包含大于或等于该结点的键值。如果我们交换每个节点的左子树和右子树,得到的树叫做镜像二叉搜索树。

现在我们给出一个整数键值序列,请编写程序判断该序列是否为某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,如果是,则输出对应二叉树的后序遍历序列。

输入格式:

输入的第一行包含一个正整数N(≤1000),第二行包含N个整数,为给出的整数键值序列,数字间以空格分隔。

输出格式:

输出的第一行首先给出判断结果,如果输入的序列是某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,则输出YES,否侧输出NO。如果判断结果是YES,下一行输出对应二叉树的后序遍历序列。数字间以空格分隔,但行尾不能有多余的空格。

输入样例1:
7
8 6 5 7 10 8 11
输出样例1:
YES
5 7 6 8 11 10 8
输入样例2:
7
8 6 8 5 10 9 11
输出样例2:
NO

7-13 肿瘤诊断 (30分)

在诊断肿瘤疾病时,计算肿瘤体积是很重要的一环。给定病灶扫描切片中标注出的疑似肿瘤区域,请你计算肿瘤的体积。

输入格式:

输入第一行给出4个正整数:MNLT,其中MN是每张切片的尺寸(即每张切片是一个M×N的像素矩阵。最大分辨率是1286×128);L(≤60)是切片的张数;T是一个整数阈值(若疑似肿瘤的连通体体积小于T,则该小块忽略不计)。

最后给出L张切片。每张用一个由0和1组成的M×N的矩阵表示,其中1表示疑似肿瘤的像素,0表示正常像素。由于切片厚度可以认为是一个常数,于是我们只要数连通体中1的个数就可以得到体积了。麻烦的是,可能存在多个肿瘤,这时我们只统计那些体积不小于T的。两个像素被认为是“连通的”,如果它们有一个共同的切面,如下图所示,所有6个红色的像素都与蓝色的像素连通。

img

输出格式:

在一行中输出肿瘤的总体积。

输入样例:
3 4 5 2
1 1 1 1
1 1 1 1
1 1 1 1
0 0 1 1
0 0 1 1
0 0 1 1
1 0 1 1
0 1 0 0
0 0 0 0
1 0 1 1
0 0 0 0
0 0 0 0
0 0 0 1
0 0 0 1
1 0 0 0
输出样例:
26

7-14 凑零钱 (30分)

韩梅梅喜欢满宇宙到处逛街。现在她逛到了一家火星店里,发现这家店有个特别的规矩:你可以用任何星球的硬币付钱,但是绝不找零,当然也不能欠债。韩梅梅手边有 104 枚来自各个星球的硬币,需要请你帮她盘算一下,是否可能精确凑出要付的款额。

输入格式:

输入第一行给出两个正整数:N(≤104)是硬币的总个数,M(≤102)是韩梅梅要付的款额。第二行给出 N 枚硬币的正整数面值。数字间以空格分隔。

输出格式:

在一行中输出硬币的面值 V1≤V2≤⋯≤V**k,满足条件 V1+V2+...+V**k=M。数字间以 1 个空格分隔,行首尾不得有多余空格。若解不唯一,则输出最小序列。若无解,则输出 No Solution

注:我们说序列{ A[1],A[2],⋯ }比{ B[1],B[2],⋯ }“小”,是指存在 k≥1 使得 A[i]=B[i] 对所有 i<k 成立,并且 A[k]<B[k]。

输入样例 1:
8 9
5 9 8 7 2 3 4 1
输出样例 1:
1 3 5
输入样例 2:
4 8
7 2 4 3
输出样例 2:
No Solution

7-15 社交集群 (30分)

当你在社交网络平台注册时,一般总是被要求填写你的个人兴趣爱好,以便找到具有相同兴趣爱好的潜在的朋友。一个“社交集群”是指部分兴趣爱好相同的人的集合。你需要找出所有的社交集群。

输入格式:

输入在第一行给出一个正整数 N(≤1000),为社交网络平台注册的所有用户的人数。于是这些人从 1 到 N 编号。随后 N 行,每行按以下格式给出一个人的兴趣爱好列表:

K**i: h**i[1] h**i[2] ... h**i[K**i]

其中K**i(>0)是兴趣爱好的个数,h**i[j]是第j个兴趣爱好的编号,为区间 [1, 1000] 内的整数。

输出格式:

首先在一行中输出不同的社交集群的个数。随后第二行按非增序输出每个集群中的人数。数字间以一个空格分隔,行末不得有多余空格。

输入样例:
8
3: 2 7 10
1: 4
2: 5 3
1: 4
1: 3
1: 4
4: 6 8 1 5
1: 4
输出样例:
3
4 3 1
posted @ 2020-07-14 20:31  神奇周一  阅读(324)  评论(0)    收藏  举报