【超高效程式碼】1059 C語言競賽 (20分)
立志用更少的程式碼做更高效的表達
Pat乙級最優化程式碼+題解+分析彙總——>傳送門
C 語言競賽是浙江大學計算機學院主持的一個歡樂的競賽。既然競賽主旨是為了好玩,頒獎規則也就制定得很滑稽:
0、冠軍將贏得一份“神祕大獎”(比如很巨大的一本學生研究論文集……)。
1、排名為素數的學生將贏得最好的獎品 —— 小黃人玩偶!
2、其他人將得到巧克力。
給定比賽的最終排名以及一系列參賽者的 ID,你要給出這些參賽者應該獲得的獎品。
輸入格式:
輸入第一行給出一個正整數 N(≤10^4 ),是參賽者人數。隨後 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 Award2222: Are you kidding?
8888: Checked
2222: Are you kidding?
解析
如果每輸入一個數,都判斷它是否為素數, 那麼時間複雜度會非常高, 而本題又規定了輸入數的範圍(小於1w),因此考慮用篩選法求素數。
這種方法比較好理解:初始時,假設全部都是素數,當找到一個素數時,顯然這個素數乘上另外一個數之後都是合數(i是素數,那麼i1,i2…i*n就是合數),把這些合數都篩掉,即演算法名字的由來。(這裡我用的是非線性篩,雖然效率不如線性晒,但更好理解,對付本題也足夠了~)
求出素數後,進行如下分類:
- 如果是第一個輸入的數,則置為3
- 如果是素數,則對應的值置為1
- 如果不是素數,則置為-1
接下來進行遍歷,判斷即可。
程式碼
#include<bits/stdc++.h>
using namespace std;
int a[10010] = {0}, b[10010] = {0}; //a陣列判斷是否是素數,b陣列存放具體值
int main() {
a[0] = a[1] = 1;
for(int i = 2; i < 10010/2; i++)
if(a[i] == 0)
for(int j = i*2; j <= 10010; j += i)
a[j] = 1;
int n; cin>>n;
int first;
for(int i = 1; i <= n; i++) {
int x; cin >> x;
if(i == 1) { b[x] = 3; continue; } //代表是冠軍
if(a[i] == 0) b[x] = 1; //如果是素數
else b[x] = -1; //如果不是素數
}
cin >> n;
for(int i = 0; i < n; i++) {
int x; cin >> x;
if(b[x] == 3) { //如果是冠軍
printf("%04d: Mystery Award\n",x);
b[x] = 2;
}
else if(b[x] == 1) { //如果是素數
printf("%04d: Minion\n", x);
b[x] = 2;
}
else if(b[x] == -1) { //如果不是素數
printf("%04d: Chocolate\n", x);
b[x] = 2;
}
else if(b[x] == 2) { //如果領過獎
printf("%04d: Checked\n", x);
} else { //沒有出現過的序號
printf("%04d: Are you kidding?\n", x);
}
}
return 0;
}