1. 程式人生 > 其它 >【超高效程式碼】1059 C語言競賽 (20分)

【超高效程式碼】1059 C語言競賽 (20分)

技術標籤:PAT乙級PATPAT乙級

立志用更少的程式碼做更高效的表達


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 Award

2222: 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;
}

沖沖衝~ PAT加油~

在這裡插入圖片描述