目录
1059:C语言竞赛
输入格式:
输出格式:
输入样例:
输出样例:
思路:
1.结构:
2.判断素数
3.输出宽度调整
代码:
时间复杂度:
总结:
题目链接:
C 语言竞赛是浙江大学计算机学院主持的一个欢乐的竞赛。既然竞赛主旨是为了好玩,颁奖规则也就制定得很滑稽:
给定比赛的最终排名以及一系列参赛者的 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
因为这道题的各种数据较多,我们也可以写一个结构:
struct 结构名{
string 奖品.
bool 是否是一个素数.
bool 是否已经被查找过了.
int 这个学生的排名.
}
因为题目规定ID最大是9999,所以我们可以定一个长度为10000的结构数组a.
现在我们要写一个判断是否是一个素数的函数:
素数是什么?
除了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)的时间:
我们在结构体中的一个变量初始化一个标记,如果输入了一个学生,就把这个学生的标记擦除!
判断的时候只需要看一下是否有这个标记就可以了.
在询问中,我们输出ID的时候,可以利用以下几点:
setw函数设置宽度.
setfill函数设置如果宽度不足,就补充一个字符.
因为题目要求是四位,所以我们可以设置宽度为4,如果不足四位,补充字符'0'.
因为根据题目要求,必须要输出四位的数字,哪怕是1也要输出0001,这里我们将要输出的整数看作s.
这个语句的结果就是看s的长度是多少,如果是4位,那么直接就输出s.
如果没有四位,就把空格的地方左边来补充'0'输出s.
这里不存在超过四位,因为题目已经说明了输入的是一个四位整数.
//1059:C语言竞赛
//正解:
#include
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<
O(k+n*(sqrt(1)+.......+sqrt(n));
相当于O(k+nlogn);
这道题运用了结构体,流操作算子(设置宽度),素数判断的知识,结合起来,对于初学者来说,还是比较难的!
PTA | 程序设计类实验辅助教学平台千名教师建设,万道高质量题目,百万用户拼题的程序设计实验辅助教学平台
https://pintia.cn/problem-sets/994805260223102976/exam/problems/994805269828059136 
下一篇:我应该是懂居家办公的吧?