2020.11.22-天梯练习赛补题
7-2 打印沙漏
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
*****
***
*
***
*****
2
题解:先输出上半部分,计算出共有多少行以及最多的符号数目,记录下空格,按照规律排列输出,再照着输出下半部分
注意要在最后一行输出剩下没用掉的符号数,用完也要输出0
#include<bits/stdc++.h> using namespace std; bool cmp(string a,string b) { return a>b; } int main() { int n; char ch; scanf("%d %c",&n,&ch); if(n<=0||n>1000) ; else { int m=n; n-=1; int i=3,j=0; //cout<<ch<<"*"<<endl; while(n>=0) { if(i*2<=n) { j++; n-=i*2; i+=2; } else break; } i-=2; int kg=0; for(int x=0;x<j;x++) { for(int w=0;w<kg;w++)cout<<" "; // cout<<ch<<"&&"<<endl; for(int q=0;q<i;q++)cout<<ch; kg+=1; i-=2; cout<<endl; } for(int w=0;w<kg;w++)cout<<" "; cout<<ch<<endl; kg-=1; i+=2; for(int x=0;x<j;x++) { for(int w=0;w<kg;w++)cout<<" "; for(int q=0;q<i;q++)cout<<ch; kg-=1; i+=2; cout<<endl; } cout<<n<<endl; } }
7-4 倒数第N个字符串
给定一个完全由小写英文字母组成的字符串等差递增序列,该序列中的每个字符串的长度固定为 L,从 L 个 a 开始,以 1 为步长递增。例如当 L 为 3 时,序列为 { aaa, aab, aac, ..., aaz, aba, abb, ..., abz, ..., zzz }。这个序列的倒数第27个字符串就是 zyz。对于任意给定的 L,本题要求你给出对应序列倒数第 N 个字符串。
输入格式:
输入在一行中给出两个正整数 L(2 ≤ L ≤ 6)和 N(≤)。
输出格式:
在一行中输出对应序列倒数第 N 个字符串。题目保证这个字符串是存在的。
输入样例:
3 7417
输出样例:
pat
题解:共有26个字母,长度为L,所以可以得到共有26^L种字符串,题目要求输出倒数第N个字符串,可以计算出它是正数第几个,联想十进制的每位求法,然后转换为26进制求,对26取模在加‘a’即可
#include<bits/stdc++.h> using namespace std; bool cmp(string a,string b) { return a>b; } int main() { int l,n; cin>>l>>n; int m=pow(26,l)-n; int i=0,j; char s[100]; while(l--) { s[i++]=m%26+'a'; m/=26; } for(j=i-1;j>=0;j--)cout<<s[j]; cout<<endl; }
7-5 整除光棍
这里所谓的“光棍”,并不是指单身汪啦~ 说的是全部由1组成的数字,比如1、11、111、1111等。传说任何一个光棍都能被一个不以5结尾的奇数整除。比如,111111就可以被13整除。 现在,你的程序要读入一个整数x,这个整数一定是奇数并且不以5结尾。然后,经过计算,输出两个数字:第一个数字s,表示x乘以s是一个光棍,第二个数字n是这个光棍的位数。这样的解当然不是唯一的,题目要求你输出最小的解。
提示:一个显然的办法是逐渐增加光棍的位数,直到可以整除x为止。但难点在于,s可能是个非常大的数 —— 比如,程序输入31,那么就输出3584229390681和15,因为31乘以3584229390681的结果是111111111111111,一共15个1。
输入格式:
输入在一行中给出一个不以5结尾的正奇数x(<)。
输出格式:
在一行中输出相应的最小的s和n,其间以1个空格分隔。
输入样例:
31
输出样例:
3584229390681 15
#include<bits/stdc++.h> using namespace std; int main() { int x; cin>>x; int s,n; string b; int sum; char l; if(x==1)sum=1,n=1;//x<1000,可以先列出可能的光棍数值 else if(x<=11)sum=11,n=2; else if(x<=111)sum=111,n=3; else if(x<=1000)sum=1111,n=4; int t,p=0; while(1) { t=sum/x; printf("%d",t); if(sum%x==0)break; n++; sum=(sum%x)*10+1;//当除数不够时商*10+1 } cout<<" "<<n<<endl; }
7-12 列车调度
火车站的列车调度铁轨的结构如下图所示。
两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?
输入格式:
输入第一行给出一个整数N (2 ≤ N ≤),下一行给出从1到N的整数序号的一个重排列。数字间以空格分隔。
输出格式:
在一行中输出可以将输入的列车按序号递减的顺序调离所需要的最少的铁轨条数。
输入样例:
9
8 4 2 5 3 9 1 6 7
输出样例:
4
题解:运用set里的lower_bound函数只记录最小的数,此时为一组,当出现比它大的数时就将此数插入数组中,出现第二组,再依次比较选出比它小的,直到出现比它大的数,就是另外一组,以此类推
#include<bits/stdc++.h> using namespace std; int main() { int n; cin>>n; set<int>s; for(int i=0;i<n;i++) { int k; cin>>k; set<int>::iterator it=s.lower_bound(k); if(it!=s.end()) { s.erase(it);//删除之前放进数组里比此时的k大的数 s.insert(k); } else { s.insert(k); } } cout<<s.size()<<endl; }
7-9 红色警报
战争中保持各个城市间的连通性非常重要。本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报。注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不改变其他城市之间的连通性,则不要发出警报。
输入格式:
输入在第一行给出两个整数N(0 < N ≤ 500)和M(≤ 5000),分别为城市个数(于是默认城市从0到N-1编号)和连接两城市的通路条数。随后M行,每行给出一条通路所连接的两个城市的编号,其间以1个空格分隔。在城市信息之后给出被攻占的信息,即一个正整数K和随后的K个被攻占的城市的编号。
注意:输入保证给出的被攻占的城市编号都是合法的且无重复,但并不保证给出的通路没有重复。
输出格式:
对每个被攻占的城市,如果它会改变整个国家的连通性,则输出Red Alert: City k is lost!,其中k是该城市的编号;否则只输出City k is lost.即可。如果该国失去了最后一个城市,则增加一行输出Game Over.。
输入样例:
5 4
0 1
1 3
3 0
0 4
5
1 2 0 4 3
输出样例:
City 1 is lost.
City 2 is lost.
Red Alert: City 0 is lost!
City 4 is lost.
City 3 is lost.
Game Over.
题解:运用到了并查集
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; struct p{ int x;//城市 int y; }s[5001];//记录哪两个城市相连接,存放两城市的连接关系 int fa[505];//用来找根的关系 int find(int x)//查找根 { while(x != fa[x]) { x = fa[x]; } return x; } void show(int x,int y)//合并 { int x1 = find(x); int y1 = find(y); if(x1 != y1)//如果两个不属于同一个根,就合并为一个根 { fa[x1] = y1; } } int main() { int n,m,u,v; int str[1000];//用于标记 cin>>n>>m; for(int j=0;j<n;j++) { fa[j]=j;//初始化时每个人的根都设为自己 } for(int i=0;i<m;i++) { cin>>u>>v; s[i].x = u; s[i].y = v; show(u,v);//连通的城市并起来 } int sum=0;//记录城市分几块 for(int i=0;i<n;i++) { if(i == fa[i])//如果根就是自己 sum++; } int k,num; cin>>k; memset(str,0,sizeof(str));//标记城市被攻占 for(int i=0;i<k;i++) { for(int j=0;j<n;j++)//输入被攻占的城市时,需要重新初始化 { fa[j]=j;//初始化时每个人的根都是自己 } cin>>num; str[num]=1; for(int i=0;i<m;i++) { if(str[s[i].x] == 1 || str[s[i].y] == 1) continue; show(eg[i].x, eg[i].y); } int ct=0; for(int i=0;i<n;i++) { if(fa[i] == i) ct++; } if(ct-1 == sum||ct == sum) printf("City %d is lost.\n",num); else printf("Red Alert: City %d is lost!\n", num); sum=ct; } if(k >= n) printf("Game Over.\n"); }

浙公网安备 33010602011771号