开始向 PAT 甲级进发哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈啊哈哈哈哈哈哈啊哈哈哈哈哈哈啊哈哈哈啊哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈啊哈哈哈哈哈哈啊哈哈哈哈哈哈啊哈哈哈啊哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈啊哈哈哈哈哈哈啊哈哈哈哈哈哈啊哈哈哈啊哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈啊哈哈哈哈哈哈啊哈哈哈哈哈哈啊哈哈哈啊哈哈哈
一、题目
PAT 准考证号由 4 部分组成:
第 1 位是级别,即 T 代表顶级;A 代表甲级;B 代表乙级;
第 2~4 位是考场编号,范围从 101 到 999;
第 5~10 位是考试日期,格式为年、月、日顺次各占 2 位;
最后 11~13 位是考生编号,范围从 000 到 999。
现给定一系列考生的准考证号和他们的成绩,请你按照要求输出各种统计信息。
输入格式:
输入首先在一行中给出两个正整数 N(≤10^4 )和 M(≤100),分别为考生人数和统计要求的个数。
接下来 N 行,每行给出一个考生的准考证号和其分数(在区间 [0,100] 内的整数),其间以空格分隔。
考生信息之后,再给出 M 行,每行给出一个统计要求,格式为:类型 指令,其中
类型 为 1 表示要求按分数非升序输出某个指定级别的考生的成绩,对应的 指令 则给出代表指定级别的字母;
类型 为 2 表示要求将某指定考场的考生人数和总分统计输出,对应的 指令 则给出指定考场的编号;
类型 为 3 表示要求将某指定日期的考生人数分考场统计输出,对应的 指令 则给出指定日期,格式与准考证上日期相同。
输出格式:
对每项统计要求,首先在一行中输出
Case #: 要求
其中 # 是该项要求的编号,从 1 开始;要求 即复制输入给出的要求。随后输出相应的统计结果:
类型 为 1 的指令,输出格式与输入的考生信息格式相同,即 准考证号 成绩。对于分数并列的考生,按其准考证号的字典序递增输出(题目保证无重复准考证号);
类型 为 2 的指令,按 人数 总分 的格式输出;
类型 为 3 的指令,输出按人数非递增顺序,格式为 考场编号 总人数。若人数并列则按考场编号递增顺序输出。
如果查询结果为空,则输出 NA。
输入样例:
8 4
B123180908127 99
B102180908003 86
A112180318002 98
T107150310127 62
A107180908108 100
T123180908010 78
B112160918035 88
A107180908021 98
1 A
2 107
3 180908
2 999
输出样例:
Case 1: 1 A
A107180908108 100
A107180908021 98
A112180318002 98
Case 2: 2 107
3 260
Case 3: 3 180908
107 2
123 2
102 1
Case 4: 2 999
NA
作者: 陈越
单位: 浙江大学
时间限制: 200 ms
内存限制: 64 MB
代码长度限制: 16 KB
二、思路
由题意,一条13位的准考证包含了四条信息,为了便于处理,将准考证按功能按位拆开保存在结构体中:
(char)Lev:等级
(int)Room:考场
(int)ID:考生编号
(int)Date:考试日期
(int)Score:考试成绩
然后根据给定Mode(1、2、3)进行分类处理。
处理内容不再详述,没有什么易错的地方
唯一有一个坑:
按照这种思路处理,会遇到 测试点1、测试点4答案错误
原因是:
按照要求,进行统计处理时,先输出:
Case #: 要求
要求 即复制输入给出的要求
最初我是将要求的指令根据Mode分别用char,int存放的,但若输入指令非法时,就不能做到复制给出的要求。
改进:
将指令类型统一读入,用字符串Order处理,然后分别转为char、int(atoi()函数),通过。
三、代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct
{
char Lev;//等级:T/A/B
int Room,ID,Score,Date;//Room:考场,ID:考生编号,Score:成绩 Date:日期
}PAT;
typedef struct
{
int Room,Count;
}Mode3;
int cmpM1(const void * a,const void * b)
{
PAT p= * (PAT *) a,q= * (PAT *)b;
if( p.Score != q.Score)
return q.Score-p.Score;
else
{
if( p.Room != q.Room )
return p.Room-q.Room;
else
{
if( p.Date != q.Date )
return p.Date-q.Date;
else
return p.ID-q.ID;
}
}
}
int cmpM3(const void * a,const void * b)
{
Mode3 p= * (Mode3 *) a,q= * (Mode3 *)b;
if( p.Count != q.Count )
return q.Count-p.Count;
else
return p.Room-q.Room;
}
int main()
{
int M,N,i,j,Mode,nM1,nM2,nM3,R,D,SumM2;
char L,Order[100];
scanf("%d %d",&N,&M);
PAT P[N];
for(i=0 ; i<N ; i++)
scanf("\n%c%3d%6d%3d %d",&P[i].Lev,&P[i].Room,&P[i].Date,&P[i].ID,&P[i].Score);
for(i=0 ; i<M ; i++)
{
scanf("%d %s",&Mode,Order);
printf("Case %d: %d %s\n",i+1,Mode,Order);
if( Mode == 1 )
{
L=Order[0];
PAT M1[N];
for(nM1=0,j=0 ; j<N ; j++)
if( P[j].Lev == L )
M1[nM1++]=P[j];
if( nM1 == 0 )
printf("NA\n");
else
{
qsort(M1,nM1,sizeof(PAT),cmpM1);
for(j=0 ; j<nM1 ; j++)
printf("%c%03d%06d%03d %d\n",M1[j].Lev,M1[j].Room,M1[j].Date,M1[j].ID,M1[j].Score);
}
}
else if( Mode == 2 )
{
R=atoi(Order);
for(nM2=0,SumM2=0,j=0 ; j<N ; j++)
if( P[j].Room == R )
{
nM2++;
SumM2+=P[j].Score;
}
if( nM2 == 0 )
printf("NA\n");
else
printf("%d %d\n",nM2,SumM2);
}
else if( Mode == 3 )
{
int Temp[1000]={0};
Mode3 M3[N];
D=atoi(Order);
for(nM3=0,j=0 ; j<N ; j++)
{
if( P[j].Date == D )
{
if( Temp[ P[j].Room ] == 0 )
M3[nM3++].Room=P[j].Room;
Temp[ P[j].Room ]++;
}
}
if( nM3 == 0 )
printf("NA\n");
else
{
for(j=0 ; j<nM3 ; j++)
M3[j].Count=Temp[M3[j].Room];
qsort(M3,nM3,sizeof(Mode3),cmpM3);
for(j=0 ; j<nM3 ; j++)
printf("%03d %d\n",M3[j].Room,M3[j].Count);
}
}
}
return 0;
}