经过PTA甲和天梯选拔我对自己产生了严重的怀疑,我不知道我现在坚持的是不是对的。我不能说我自己是最努力的那个,但肯定是最努力的那些人中的一个,我不知道为什么差距会那么大。也不知道怎么才能从自我否定、自我怀疑里把自己拉出来。
我只能说,可能是我学的还不够,学习方法不正确,可能我想得太多,可能我太敏感。我以为我把自己从什么社团组织里拖出来就能静下心来,我以为我把追求者们的路一下子截断就可以让自己不进感情的坑,我以为我把我自己完全投入到学习里就可以学得很好。我总是在做每件事的时候都有一份期待在里面,这份期待往往会让我失望透顶。
再试一次吧,还有蓝桥呢,我不信我不行,我也不信,他们天生就比我强,我不信。
L1-1 天梯赛座位分配 (20 分)
天梯赛每年有大量参赛队员,要保证同一所学校的所有队员都不能相邻,分配座位就成为一件比较麻烦的事情。为此我们制定如下策略:假设某赛场有 N 所学校参赛,第 i 所学校有 M[i] 支队伍,每队 10 位参赛选手。令每校选手排成一列纵队,第 i+1 队的选手排在第 i 队选手之后。从第 1 所学校开始,各校的第 1 位队员顺次入座,然后是各校的第 2 位队员…… 以此类推。如果最后只剩下 1 所学校的队伍还没有分配座位,则需要安排他们的队员隔位就坐。本题就要求你编写程序,自动为各校生成队员的座位号,从 1 开始编号。
输入在一行中给出参赛的高校数 N (不超过100的正整数);第二行给出 N 个不超过10的正整数,其中第 i 个数对应第 i 所高校的参赛队伍数,数字间以空格分隔。
从第 1 所高校的第 1 支队伍开始,顺次输出队员的座位号。每队占一行,座位号间以 1 个空格分隔,行首尾不得有多余空格。另外,每所高校的第一行按“#X”输出该校的编号X,从 1 开始。
3
3 4 2
#1
1 4 7 10 13 16 19 22 25 28
31 34 37 40 43 46 49 52 55 58
61 63 65 67 69 71 73 75 77 79
#2
2 5 8 11 14 17 20 23 26 29
32 35 38 41 44 47 50 53 56 59
62 64 66 68 70 72 74 76 78 80
82 84 86 88 90 92 94 96 98 100
#3
3 6 9 12 15 18 21 24 27 30
33 36 39 42 45 48 51 54 57 60
#include
#include
#include
using namespace std;
#define maxn 105
int res[105][105][105];
int n;
int team[maxn];
int maxx = 0;
int main()
{
scanf("%d",&n);
for(int i = 0; i < n; i ++)
{
scanf("%d",&team[i]);
maxx = max(maxx,team[i]);//找出数量最大的队伍。
}
int lastshool = -1;
int position = 0;
for(int j = 0; j < maxx; j ++)
{
for(int k = 0; k < 10; k ++)
{
for(int i = 0; i < n; i ++)
{
if(j
L1-2 Excel列名和列序号转换 (15 分)
大家有没有留意过Excel表格中列名的规律呢?是这样的:A B C ... Y Z AA AB AC ... AY AZ BA BB BC ... BY BZ ... ZZ ... AAA ...
如果没看懂,请打开Excel程序仔细观察一下~~
每一列都是有序号的,从1
开始编号,即:列A B C ... Y Z AA AB ...
的编号依次是 1 2 3 ... 25 26 27 28 ...
现在,请编写程序,按照上述规律,把输入的列名和列序号进行相互转换(不用考虑Excel软件实际允许的最多列数)。
输入由若干行组成,每行的内容是以下三种之一:
#
,表示输入结束对于在输入结束符#
之前出现的每一行输入,若输入为列名,在一行内打印对应的列序号;若输入为列序号,在一行内打印对应的列名。
A
3
AB
29
#
1
C
28
AC
#include
#include
#include
using namespace std;
char indexs[105];
int main()
{
string a;
int flag = 0;
while(cin>>a)
{
if(a=="#")
break;
flag = 0;
int cnt = 0;
int len = a.length();
long long int num = 0;
for(int i = 0; i < len; i ++)
{
if(a[i]>='0'&&a[i]<='9')
num = num*10 + a[i] - '0';
else
{
num = num*26 + a[i]-'A' + 1;
flag = 1;
}
}
if(flag)
printf("%d\n",num);
else
{
while(num)
{
if(num%26==0)
{
indexs[cnt] = 26+64;
cnt++;
num = num/26;
num--;
}
else
{
indexs[cnt] = num%26 + 64;
cnt++;
num /= 26;
}
}
for(int i = cnt - 1; i >= 0; i --)
printf("%c",indexs[i]);
printf("\n");
}
}
}
L1-3 算术入门之加减乘除 (5 分)
对于输入的两个整数,按照要求输出其和差积商。
在一行内输入两个不超过100的非负整数a和b,中间以一个空格间隔,且保证b不为0。
共四行,格式是:
[a] + [b] = [a+b]
[a] - [b] = [a-b]
[a] * [b] = [a*b]
[a] / [b] = [a/b]
其中,带有方括号的内容(如[a]
、[b]
、[a+b]
等)表示相应整数或运算结果的值,在输出时要用实际的值代替。
并且:如果a能够被b整除,那么a/b应输出为整数格式,否则a/b输出为带两位小数的格式。
提示:注意表达式中的空格。
6 3
6 + 3 = 9
6 - 3 = 3
6 * 3 = 18
6 / 3 = 2
8 6
8 + 6 = 14
8 - 6 = 2
8 * 6 = 48
8 / 6 = 1.33
#include
#include
#include
using namespace std;
#define maxn 105
int main()
{
int a,b;
scanf("%d %d",&a,&b);
printf("%d + %d = %d\n",a,b,a+b);
printf("%d - %d = %d\n",a,b,a-b);
printf("%d * %d = %d\n",a,b,a*b);
if(a%b)
{
double c = 1.0*a/b;
printf("%d / %d = %.2f\n",a,b,c);
}
else
printf("%d / %d = %d\n",a,b,a/b);
}
L1-4 Say Hello to Integers (5 分)
Say hello to integers? Yes! 你没看错! 现在我们来向整数说“你好~” 本题读入两个整数,然后输出对她们的问候语。
输入格式:
在一行中给出两个绝对值不超过32767的整数A和B,两数之间有一个空格
输出格式:
在一行中输出 "Hello, A and B!" (其中A和B用实际输入的整数代替)
输入样例:
1949 2015
输出样例:
Hello, 1949 and 2015!
#include
#include
#include
using namespace std;
#define maxn 105
int main()
{
int a,b;
scanf("%d %d",&a,&b);
printf("Hello, %d and %d!",a,b);
}
L1-5 刷题与Z老师的头发 (10 分)
在Pintia上,每天Z老师出题、小盆友们刷题。Z老师的头发遵从以下规律:
1、每天生长出60根头发;
2、每出一道题,减少20根头发;
3、每天结束时统计累积做题情况:
(1)若出的题全部被做出来,则Z老师产生“没题焦虑”,减少30根头发;
(2)若小盆友做出来的题少于50%,则Z老师产生“学生不用功焦虑”,减少70根头发。
现给定连续N天的出题、刷题情况,请计算Z老师头发的变化情况。
第一行输入一个正整数N
(N<20
);
接下来N
行,每行输入两个非负整数,分别是一天的出题数量q
和刷题(做出来)数量s
,以空格间隔。
题目输入保证出题总数量不超过N*10
,并且每天的刷题量不会使累积刷题数量超过累积出题数量。
若Z老师头发增加K
根,则输出+K
;若Z老师头发减少K
根,则输出-K
;若没有变化,则输出--
3
5 3
5 1
5 11
-220
3
3 2
3 2
3 2
--
这个题最后也没AC, 看了舍友的代码才知道要出题量和刷题量都要累加。
#include
using namespace std;
int main(void){
int n;
int sumc = 0, sumz = 0;
int a, b;
int k = 0;
scanf("%d", &n);
for(int i = 0; i < n; i++){
k = k + 60;
scanf("%d %d", &a, &b);
k = k - a * 20;
sumc += a;
sumz += b;
if(0.5 * sumc > 1.0 * sumz) k = k - 70;
if(sumc == sumz) k = k - 30;
}
if(k > 0){
printf("+%d\n", k);
}
else if (k < 0){
printf("%d\n", k);
}
else{
printf("--\n");
}
return 0;
}
L1-6 福到了 (15 分)
“福”字倒着贴,寓意“福到”。不论到底算不算民俗,本题且请你编写程序,把各种汉字倒过来输出。这里要处理的每个汉字是由一个 N × N 的网格组成的,网格中的元素或者为字符 @
或者为空格。而倒过来的汉字所用的字符由裁判指定。
输入在第一行中给出倒过来的汉字所用的字符、以及网格的规模 N (不超过100的正整数),其间以 1 个空格分隔;随后 N 行,每行给出 N 个字符,或者为 @
或者为空格。
输出倒置的网格,如样例所示。但是,如果这个字正过来倒过去是一样的,就先输出bu yong dao le
,然后再用输入指定的字符将其输出。
$ 9
@ @@@@@
@@@ @@@
@ @ @
@@@ @@@
@@@ @@@@@
@@@ @ @ @
@@@ @@@@@
@ @ @ @
@ @@@@@
$$$$$ $
$ $ $ $
$$$$$ $$$
$ $ $ $$$
$$$$$ $$$
$$$ $$$
$ $ $
$$$ $$$
$$$$$ $
& 3
@@@
@
@@@
bu yong dao le
&&&
&
&&&
读入一直在WA,后来用getchar(),就神奇地可以了,学到了。
读入以后逆着进一个新数组就行了。
#include
#include
#include
using namespace std;
#define maxn 2005
int n;
char ch;
char mapp[105][105];
char newmap[105][105];
int main()
{
scanf("%c",&ch);
scanf("%d",&n);
getchar();
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
mapp[i][j] = getchar();
}
getchar();
}
for(int i = 0; i < n; i ++)
for(int j = 0; j < n; j ++)
newmap[i][j] = ' ';
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
if(mapp[n-i-1][n-j-1]==' ')
newmap[i][j] = ' ';
else
newmap[i][j] = ch;
}
}
int flag = 0;
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
if(mapp[i][j]==' '&&newmap[i][j]==' ')
continue;
else if(mapp[i][j]!=' '&&newmap[i][j]!=' ')
continue;
else
{
flag = 1;
break;
}
}
if(flag)
break;
}
if(!flag)
printf("bu yong dao le\n");
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < n; j ++)
{
printf("%c",newmap[i][j]);
}
printf("\n");
}
}
L1-7 谁是赢家 (10 分)
某电视台的娱乐节目有个表演评审环节,每次安排两位艺人表演,他们的胜负由观众投票和 3 名评委投票两部分共同决定。规则为:如果一位艺人的观众票数高,且得到至少 1 名评委的认可,该艺人就胜出;或艺人的观众票数低,但得到全部评委的认可,也可以胜出。节目保证投票的观众人数为奇数,所以不存在平票的情况。本题就请你用程序判断谁是赢家。
输入第一行给出 2 个不超过 1000 的正整数 Pa 和 Pb,分别是艺人 a 和艺人 b 得到的观众票数。题目保证这两个数字不相等。随后第二行给出 3 名评委的投票结果。数字 0 代表投票给 a,数字 1 代表投票给 b,其间以一个空格分隔。
按以下格式输出赢家:
The winner is x: P1 + P2
其中 x
是代表赢家的字母,P1
是赢家得到的观众票数,P2
是赢家得到的评委票数。
327 129
1 0 1
The winner is a: 327 + 1
#include
#include
#include
using namespace std;
#define maxn 2005
int a,b;
int aa,bb;
int main()
{
scanf("%d %d",&a,&b);
for(int i = 0; i < 3; i ++)
{
int x;
scanf("%d",&x);
if(x)
bb++;
else
aa++;
}
if(aa&&a>b||aa==3)
printf("The winner is a: %d + %d",a,aa);
else if(bb&&a
L1-8 猜数字 (20 分)
一群人坐在一起,每人猜一个 100 以内的数,谁的数字最接近大家平均数的一半就赢。本题就要求你找出其中的赢家。
输入在第一行给出一个正整数N(≤104)。随后 N 行,每行给出一个玩家的名字(由不超过8个英文字母组成的字符串)和其猜的正整数(≤ 100)。
在一行中顺序输出:大家平均数的一半(只输出整数部分)、赢家的名字,其间以空格分隔。题目保证赢家是唯一的。
7
Bob 35
Amy 28
James 98
Alice 11
Jack 45
Smith 33
Chris 62
22 Amy
结构体的应用,再排个序。
#include
#include
#include
using namespace std;
#define maxn 100005
struct node{
string name;
int num;
}s[maxn];
int main()
{
int n;
scanf("%d",&n);
int sum = 0;
for(int i = 0; i < n; i ++)
{
cin>>s[i].name;
scanf("%d",&s[i].num);
sum += s[i].num;
}
int ave = sum/n;
ave = ave/2;
int minn = maxn;
int index = 0;
for(int i = 0; i < n; i ++)
{
int temp = s[i].num - ave;
if(temp < 0)
temp = -temp;
if(temp
L2-1 分而治之 (25 分)
分而治之,各个击破是兵家常用的策略之一。在战争中,我们希望首先攻下敌方的部分城市,使其剩余的城市变成孤立无援,然后再分头各个击破。为此参谋部提供了若干打击方案。本题就请你编写程序,判断每个方案的可行性。
输入在第一行给出两个正整数 N 和 M(均不超过10 000),分别为敌方城市个数(于是默认城市从 1 到 N 编号)和连接两城市的通路条数。随后 M 行,每行给出一条通路所连接的两个城市的编号,其间以一个空格分隔。在城市信息之后给出参谋部的系列方案,即一个正整数 K (≤ 100)和随后的 K 行方案,每行按以下格式给出:
Np v[1] v[2] ... v[Np]
其中 Np
是该方案中计划攻下的城市数量,后面的系列 v[i]
是计划攻下的城市编号。
对每一套方案,如果可行就输出YES
,否则输出NO
。
10 11
8 7
6 8
4 5
8 4
8 1
1 2
1 4
9 8
9 1
1 10
2 4
5
4 10 3 8 4
6 6 1 7 5 4 9
3 1 8 4
2 2 8
7 9 8 7 6 5 4 2
NO
YES
YES
NO
NO
#include
#include
#include
#include
L2-2 小字辈(左子右兄加强版) (25 分)
本题给定一个庞大家族的家谱,要请你给出最小一辈的名单。
需要注意的是,家族成员的输入方式,是按照“Left-child Right-sibling”(左儿子 右兄弟)的格式
【敲黑板】sibling的意思是兄弟/姐妹,是亲兄弟,不是“表兄弟”!2019年春季PAT中不认识单词sibling的孩纸请牢记……
注:本题是在浙江大学陈越老师的GPLT-2018决赛L2-2题目“小字辈”题意基础上改编而成。
输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号。
随后的N行,每行给出1名家族成员的编号以及他的亲属关系,格式为3个以空格间隔的整数A
B
C
,
其中的A
(范围1~N)是1名家族成员编号(每行的编号必定各不相同)B
的范围是0~N,当B
不为0,表示A
有儿子B
;C
的范围是0~N,当C
不为0,表示A
有兄弟C
。
题目保证输入是正确的,即:只有一个家族(没有分离成家族群),且家族中只有一位老祖宗(老祖宗即:他不是任何其他人的儿子)
首先输出最小的辈分(老祖宗的辈分最大、数值为 1,子孙的辈分数值逐级递增1)。
然后在第二行按递增顺序输出辈分最小的成员的编号。编号间以一个空格分隔,行首尾不得有多余空格。
5
1 2 0
2 4 3
3 0 0
4 0 5
5 0 0
3
4 5
5
2 5 3
1 2 0
3 0 0
4 0 0
5 0 4
3
4 5
#include
#define maxn 100005
#define INF 0x3f3f3f3f
using namespace std;
struct Node{
int Left;
int Right;
int flag;
}a[maxn];
int b[maxn];
int vis[maxn] = {0};
int M = 0;
void BFS(int root){
queue q;
q.push(a[root]);
while(!q.empty()){
Node t = q.front();
if(t.flag > M)
M = t.flag;
q.pop();
if(t.Left > 0 && vis[t.Left] == 0){
vis[t.Left] = 1;
a[t.Left].flag = t.flag + 1;
q.push(a[t.Left]);
}
if(t.Right > 0 && vis[t.Right] == 0){
vis[t.Right] = 1;
a[t.Right].flag = t.flag;
q.push(a[t.Right]);
}
}
}
int main(){
int n;
scanf("%d",&n);
int t;
for(int i = 0;i < maxn;i++){
a[i].Left = a[i].Right = 0;
b[i] = 0;
}
for(int i = 0;i < n;i++){
scanf("%d",&t);
scanf("%d %d",&a[t].Left,&a[t].Right);
b[a[t].Left] = 1;
b[a[t].Right] = 1;
}
int Root;
for(int i = 1;i <= n;i++){
if(b[i] == 0){
Root = i;
break;
}
}
a[Root].flag = 1;
vis[Root] = 1;
BFS(Root);
int temp = 0;
printf("%d\n",M);
for(int i = 1;i <= n;i++){
if(a[i].flag == M){
if(temp == 0){
printf("%d",i);
temp = 1;
}
else
printf(" %d",i);
}
}
return 0;
}
L2-3 名人堂与代金券 (25 分)
对于在中国大学MOOC(http://www.icourse163.org/ )学习“数据结构”课程的学生,想要获得一张合格证书,总评成绩必须达到 60 分及以上,并且有另加福利:总评分在 [G, 100] 区间内者,可以得到 50 元 PAT 代金券;在 [60, G) 区间内者,可以得到 20 元PAT代金券。全国考点通用,一年有效。同时任课老师还会把总评成绩前 K 名的学生列入课程“名人堂”。本题就请你编写程序,帮助老师列出名人堂的学生,并统计一共发出了面值多少元的 PAT 代金券。
输入在第一行给出 3 个整数,分别是 N(不超过 10 000 的正整数,为学生总数)、G(在 (60,100) 区间内的整数,为题面中描述的代金券等级分界线)、K(不超过 100 且不超过 N 的正整数,为进入名人堂的最低名次)。接下来 N 行,每行给出一位学生的账号(长度不超过15位、不带空格的字符串)和总评成绩(区间 [0, 100] 内的整数),其间以空格分隔。题目保证没有重复的账号。
首先在一行中输出发出的 PAT 代金券的总面值。然后按总评成绩非升序输出进入名人堂的学生的名次、账号和成绩,其间以 1 个空格分隔。需要注意的是:成绩相同的学生享有并列的排名,排名并列时,按账号的字母序升序输出。
10 80 5
[email protected] 78
[email protected] 87
[email protected] 65
[email protected] 96
[email protected] 39
[email protected] 87
[email protected] 80
[email protected] 88
[email protected] 80
[email protected] 70
360
1 [email protected] 96
2 [email protected] 88
3 [email protected] 87
3 [email protected] 87
5 [email protected] 80
5 [email protected] 80
结构体排序。
#include
#include
#include
#include
L2-4 秀恩爱分得快 (25 分)
古人云:秀恩爱,分得快。
互联网上每天都有大量人发布大量照片,我们通过分析这些照片,可以分析人与人之间的亲密度。如果一张照片上出现了 K 个人,这些人两两间的亲密度就被定义为 1/K。任意两个人如果同时出现在若干张照片里,他们之间的亲密度就是所有这些同框照片对应的亲密度之和。下面给定一批照片,请你分析一对给定的情侣,看看他们分别有没有亲密度更高的异性朋友?
输入在第一行给出 2 个正整数:N(不超过1000,为总人数——简单起见,我们把所有人从 0 到 N-1 编号。为了区分性别,我们用编号前的负号表示女性)和 M(不超过1000,为照片总数)。随后 M 行,每行给出一张照片的信息,格式如下:
K P[1] ... P[K]
其中 K(≤ 500)是该照片中出现的人数,P[1] ~ P[K] 就是这些人的编号。最后一行给出一对异性情侣的编号 A 和 B。同行数字以空格分隔。题目保证每个人只有一个性别,并且不会在同一张照片里出现多次。
首先输出 A PA
,其中 PA
是与 A
最亲密的异性。如果 PA
不唯一,则按他们编号的绝对值递增输出;然后类似地输出 B PB
。但如果 A
和 B
正是彼此亲密度最高的一对,则只输出他们的编号,无论是否还有其他人并列。
10 4
4 -1 2 -3 4
4 2 -3 -5 -6
3 2 4 -5
3 -6 0 2
-3 2
-3 2
2 -5
2 -6
4 4
4 -1 2 -3 0
2 0 -3
2 2 -3
2 -1 2
-3 2
-3 2
#include
#include
#include
#include
#include
#include