目录
1059:C语言竞赛
输入格式:
输出格式:
输入样例:
输出样例:
思路:
1.结构:
2.判断素数
3.输出宽度调整
代码:
时间复杂度:
总结:
题目链接:
1059:C语言竞赛
C 语言竞赛是浙江大学计算机学院主持的一个欢乐的竞赛。既然竞赛主旨是为了好玩,颁奖规则也就制定得很滑稽:
- 0、冠军将赢得一份“神秘大奖”(比如很巨大的一本学生研究论文集……)。
- 1、排名为素数的学生将赢得最好的奖品 —— 小黄人玩偶!
- 2、其他人将得到巧克力。
给定比赛的最终排名以及一系列参赛者的 ID,你要给出这些参赛者应该获得的奖品。
输入格式:
输入第一行给出一个正整数 N(≤104),是参赛者人数。随后 N 行给出最终排名,每行按排名顺序给出一位参赛者的 ID(4 位数字组成)。接下来给出一个正整数 K 以及 K 个需要查询的 ID。
输出格式:
对每个要查询的 ID,在一行中输出 ID: 奖品
,其中奖品或者是 Mystery Award
(神秘大奖)、或者是 Minion
(小黄人)、或者是 Chocolate
(巧克力)。如果所查 ID 根本不在排名里,打印 Are you kidding?
(耍我呢?)。如果该 ID 已经查过了(即奖品已经领过了),打印 ID: Checked
(不能多吃多占)。
输入样例:
6
1111
6666
8888
1234
5555
0001
6
8888
0001
1111
2222
8888
2222
输出样例:
8888: Minion
0001: Chocolate
1111: Mystery Award
2222: Are you kidding?
8888: Checked
2222: Are you kidding?
代码长度限制
16 KB
时间限制
200 ms
内存限制
64 MB
思路:
1.结构:
因为这道题的各种数据较多,我们也可以写一个结构:
struct 结构名{
string 奖品.
bool 是否是一个素数.
bool 是否已经被查找过了.
int 这个学生的排名.
}
因为题目规定ID最大是9999,所以我们可以定一个长度为10000的结构数组a.
2.判断素数
现在我们要写一个判断是否是一个素数的函数:
素数是什么?
除了1和它本身以外没有任何的因子.
那么我们只要发现它的一个因子就可以说他不是素数,反之,返回true.
因子是什么?
一个数除以它的因子余数为0.
我们可以根据这一点来进行判断,进行for枚举.
那么范围是多少呢,1不是素数也不是合数,要在一开始进行特判.
那么初始从=2开始,小于n吗?
这样也可以,但是还可以进行优化.
拿25来说,从2枚举到25,是不是浪费了很多.
我们只要取25的根号,也就是5来当=2;<=5;
为什么呢?
因为5是他一个因子中最大的,只要看5以下的就行了.
我们来细分以下,拿24为例:
24=1*24;
24=2*12;
24=3*8;
24=4*6;
你看,我们给24开个根号,值在4~5之间,也就是说循环最多到4.
循环过程:
24%2=0;
24%3=0;
24%4=0;
你们可能会疑惑,还有12,8,6没有除余判断呢!
其实根本没有必要,2,3,4和12,8,6相乘等于24,只要2,3,4除余为0,那么代表着12,8,6和24相除余数为0.
素数的判断写完了之后,只差判断询问的这个学生是存在还是不存在:
我们可以写一个find查找函数,找到了就返回true,这样可以,但是速度太慢了.
我们其实可以在常数时间内完成,也就是O(1)的时间:
我们在结构体中的一个变量初始化一个标记,如果输入了一个学生,就把这个学生的标记擦除!
判断的时候只需要看一下是否有这个标记就可以了.
3.输出宽度调整
在询问中,我们输出ID的时候,可以利用以下几点:
setw函数设置宽度.
setfill函数设置如果宽度不足,就补充一个字符.
因为题目要求是四位,所以我们可以设置宽度为4,如果不足四位,补充字符'0'.
因为根据题目要求,必须要输出四位的数字,哪怕是1也要输出0001,这里我们将要输出的整数看作s.
这个语句的结果就是看s的长度是多少,如果是4位,那么直接就输出s.
如果没有四位,就把空格的地方左边来补充'0'输出s.
这里不存在超过四位,因为题目已经说明了输入的是一个四位整数.
代码:
//1059:C语言竞赛
//正解:
#include<bits/stdc++.h>
using namespace std;
typedef struct Student{ //定义结构体学生
string j; //学生获得的奖
bool f,c; //f为学生的排名是否为素数,c为是否ID已经查过了
int i; //代表学生的排名
Student(){ //构造函数初始化
j="-1"; //做一个标记,以后如果有询问不存在的学生,j就是-1,就很好判断了
f=false; //刚开始定义为不是素数
c=false; //刚开始定义为还没有查过
i=0; //初始排名都为0
}
}st; //简单名称
st a[10000]; //定义学生a,因为学生的ID最大是9999,所以要定10000的数组
int pd(int x){ //判断一个整数是不是素数
bool f=true; //刚开始定义为是素数
int k; //循环变量
if(x==1) //1既不是素数也不是合数,要首先排除掉
f=false;
for(k=2;k<=sqrt(x);k++){ //循环遍历,sqrt函数是求一个整数开了根号后的值.
if(x%k==0){ //素数不能和1除外和他本身除外的任何数余数为0
f=false; //代表有一个因数了,就不是素数了
break; //退出
}
else
f=true; //是素数
}
return f; //返回
}
int main(){
int n;
cin>>n; //输入n
for(int i=1;i<=n;i++){ //输入n个数
int s;
cin>>s;
a[s].i=i; //排名是按输入来的
if(pd(a[s].i)) //如果是素数
a[s].f=true,a[s].j="Minion"; //那么f为真,将奖品设为"小黄人"
else if(a[s].i==1) //如果排名为1
a[s].j="Mystery Award"; //奖品就是"神秘大奖"
else //如果以上两个都不是
a[s].j="Chocolate"; //奖品就只能是"巧克力"
}
int k;
cin>>k; //询问次数
while(k--){ //询问输入
int s;
cin>>s; //循环
cout<<setw(4)<<setfill('0')<<s<<": ";//设置宽度和宽度不足的补充
if(a[s].c==true) //如果已经查过了
cout<<"Checked"<<endl;
else if(a[s].j=="-1") //如果没有这个学生
cout<<"Are you kidding?"<<endl;
else //有这个学生
cout<<a[s].j<<endl,a[s].c=true; //输出奖品,将c设置为真,代表查过了
}
return 0;
}
时间复杂度:
O(k+n*(sqrt(1)+.......+sqrt(n));
相当于O(k+nlogn);
总结:
这道题运用了结构体,流操作算子(设置宽度),素数判断的知识,结合起来,对于初学者来说,还是比较难的!
题目链接:
PTA | 程序设计类实验辅助教学平台千名教师建设,万道高质量题目,百万用户拼题的程序设计实验辅助教学平台https://pintia.cn/problem-sets/994805260223102976/exam/problems/994805269828059136