七夕了呀,那就刷題吧~~~
本次試題依舊使用 C++ 進行求解~由於疫情原因,本次PAT由原來的線下舉辦改為線上考試9月份還有一場,想參加的小伙伴不要錯過呀
由於本人過菜,這次七夕教超打折依舊只敢去做做乙級題(截至目前已售出30份)~😂
廢話不多說,開沖!
PAT(乙級)2020年春季考試直達鏈接:這里
試題集の基本情況
對稱日(15分)
思路
- 需要處理輸入的 date
- 將月份應為簡寫轉換為對應的數字
- 將年日月按要求組合起來
- 檢驗是否為對稱日
- 可以轉換為字符串,按對應的位或者反轉進行對比
- 可以將月份與日期的和(月份 * 100 + 日期)反轉,與年份對比
這里我使用了 map 作為月份(英文 - 數字)的映射、 sprintf 格式化字符串接着按位比較~ 太香啦~~(由於太菜,使用其他方法補零補到崩潰,導致做了半個小時才AC的屑博主)
#include <cstdio>
#include <algorithm>
#include <unordered_map>
#include <string>
using std::string;
using std::unordered_map;
int main() {
unordered_map<string, int> um{
{"Jan", 1},
{"Feb", 2},
{"Mar", 3},
{"Apr", 4},
{"May", 5},
{"Jun", 6},
{"Jul", 7},
{"Aug", 8},
{"Sep", 9},
{"Oct", 10},
{"Nov", 11},
{"Dec", 12}
};
int cnt{ 0 }, year{ 0 }, day{ 0 };
char month[5];
scanf("%d", &cnt);
getchar();
for (int i = 0; i < cnt; i++) {
scanf("%s %d, %d", month, &day, &year);
char date[10];
sprintf(date, "%04d%02d%02d", year, um[string(month)], day);
int left = 0, right = 7;
while (left < right) {
if (date[left] != date[right]) {
putchar('N');
break;
}
left++;
right--;
}
if (left > right) {
putchar('Y');
}
printf(" %04d%02d%02d\n", year, um[string(month)], day);
}
return 0;
}
結論
模擬題。細心 + 技巧 + 規范輸出 = AC
超標區間(20分)
思路
害,看到這種題不要怕,只要它不搞什么奇奇怪怪的要求就直接莽!!!
題目要求按順序輸出超過 limit 的區間,那我們就可以使用兩個變量 —— left、right 作為區間的邊界范圍
每次輸出了之后記得將它們重新設為“未使用狀態”,這個未使用狀態具體是指什么,看代碼你就知道啦
代碼
#include <cstdio>
int main() {
int cnt{ 0 }, limit{ 0 }, num{ 0 }, max{ -1 };
bool flag{ false };
scanf("%d %d", &cnt, &limit);
int left{ -1 }, right{ -1 };
for (int i = 0; i < cnt; i++) {
scanf("%d", &num);
if (num > max) {
max = num;
}
if (num > limit) {
if (left != -1) {
right++;
} else {
left = i;
right = i;
}
} else {
if (right != -1) {
flag = true;
printf("[%d, %d]\n", left, right);
left = -1;
right = -1;
}
}
}
if (right != -1) {
printf("[%d, %d]\n", left, right);
} else if (!flag) {
printf("%d\n", max);
}
return 0;
}
結論
模擬題。細心 + 想辦法去模擬 + 正確處理邊界條件 = AC
錢串子的加法(20分)
思路
這道題看着很唬人,想着陳越姥姥在PTA之前還在說今年線上考試,出題要避免模板題......
哦豁,這不就是模板題嘛!字符串加法 + 一丟丟的字符處理
模板請戳 :這里!
評論區第一個就是了~~~ 光速AC😂
代碼
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using std::cin;
using std::cout;
using std::endl;
using std::string;
void addition(string& a, string& b) {
int carry = 0;
int index_a = static_cast<int>(a.length()) - 1;
int index_b = static_cast<int>(b.length()) - 1;
string ans;
while (index_a >= 0 || index_b >= 0 || carry != 0) {
if (index_a >= 0) {
if (isalpha(a[index_a])) {
carry += a[index_a] - 'a' + 10;
} else {
carry += a[index_a] - '0';
}
index_a--;
}
if (index_b >= 0) {
if (isalpha(b[index_b])) {
carry += b[index_b] - 'a' + 10;
} else {
carry += b[index_b] - '0';
}
index_b--;
}
if (carry % 30 >= 10) {
ans.push_back('a' - 10 + carry % 30);
} else {
ans.push_back('0' + carry % 30);
}
carry /= 30;
}
int index = static_cast<int>(ans.length()) - 1;
while (ans.size() > 1 && ans[index] == '0') {
ans.pop_back();
index--;
}
std::reverse(ans.begin(), ans.end());
printf("%s\n", ans.c_str());
}
int main() {
string a, b;
cin >> a >> b;
addition(a, b);
return 0;
}
結論
有些時候遇到經典的題,背背模板也沒什么嘛~~
那都是前人的智慧呀!這里的“背”不是“死背”哦,不然是會很容易忘的!
這道題有個坑點 :如果你的第三個測試點錯了,那你可來對地方了!
這道題要求我們去除前導 0,而大家的處理方法大多都一心放在去除 0 上面而忽略掉了這個情況 —— 相加的兩個數都是 0 時,結果為 0 ,這個 0 不能去掉~
我敢保證測試點3的數據就是 —— 0 0 ,故意坑你們🤣
全素日(20分)
思路
一開始看到這道題時,想着一位數、兩位數、三位數這樣一步步遞增上去檢查。But 題目要求是要按照 twitter 樣式輸出的,好吧~~
繼續暴力模擬就完事,完全用不着什么素數線性篩,直接暴力 sqrt 即可~~
代碼
#include <cstdio>
#include <string>
#include <cmath>
using std::string;
bool isPrime(int num) {
if (num < 2) {
return false;
}
for (int i = 2; i <= static_cast<int>(sqrt(num)); i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
void judge(int num) {
char date[10];
sprintf(date, "%08d", num);
string str{ date };
bool all{ true };
for (int i = 0; i < str.length(); i++) {
string temp = str.substr(i);
bool flag = isPrime(stoi(temp));
if (!flag) {
all = false;
}
printf("%s %s\n", temp.c_str(), flag ? "Yes" : "No");
}
if (all) {
puts("All Prime!");
}
}
int main() {
int num{ 0 };
scanf("%d", &num);
judge(num);
return 0;
}
結論
如果你是測試點2、5答案錯誤而來的,那你沒有白來~
提供測試點 :00010101
哈哈,發現問題所在了吧,這種奇奇怪怪的邊界條件就是卡你的測試點(sprintf 永遠的神!)~
處理好他們就可以 AC 啦!
裁判機(25分)
思路
可可愛愛沒有腦袋~~ 又到了最后的 25 分題了,有點小緊張~(* ̄3 ̄)╭
其實很簡單啦,只是這個通過率有點讓人害怕而已🤗
這題需要用到工具人 —— unordered_set 和 vector ,如果小伙伴沒有見過這個玩意兒,不用慌~
指路👉 tools
學成歸來還請賞個贊吶~~~
簡單來說就是把初始的兩個數加到 set 里,然后根據回合依次判斷 player 的數字是否合法。具體做法就是看他說的數加上 set 中的某個數是否存在與 set 中,如果存在,則合法,把他說的數加進set。否則淘汰,這里有個需要注意的點就是,如果某人在第 n 輪淘汰了,那么后面的 n + m (m > 0)輪都可以跳過他了~~~
廢話不多說,直接開沖!
代碼
#include <cstdio>
#include <unordered_set>
#include <vector>
using std::vector;
using std::unordered_set;
int main() {
int fst{ 0 }, sec{ 0 };
int row{ 0 }, col{ 0 };
scanf("%d %d", &fst, &sec);
scanf("%d %d", &row, &col);
vector<vector<int>> v(row, vector<int>(col));
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
scanf("%d", &v[i][j]);
}
}
vector<bool> player(row, true);
unordered_set<int> us{ fst, sec };
for (int i = 0; i < col; i++) {
for (int j = 0; j < row; j++) {
if (!player[j]) {
continue;
}
if (us.count(v[j][i])) {
printf("Round #%d: %d is out.\n", i + 1, j + 1);
player[j] = false;
} else {
bool valid{ false };
for (auto& x : us) {
if (us.count(x + v[j][i])) {
valid = true;
us.insert(v[j][i]);
break;
}
}
if (!valid) {
printf("Round #%d: %d is out.\n", i + 1, j + 1);
player[j] = false;
}
}
}
}
bool flag{ false };
for (int i = 0; i < row; i++) {
if (player[i]) {
if (!flag) {
printf("Winner(s):");
flag = true;
}
printf(" %d", i + 1);
}
}
if (!flag) {
puts("No winner.");
}
return 0;
}
結論
STL 真香!你知道嗎,乙級題最后一題就喜歡考STL的使用哦~~
總結
做了這幾年的乙級題,感覺風格越來越收斂了,這次的乙級試題做下來,整體感覺難度和19年冬難度差不多~~
這次的試題難度放在乙級題庫里的話,難度算是中等偏易了(沒有今年的520鑽石爭霸賽難)
如果你是備考乙級的小伙伴,那么我推薦你去多做做乙級題庫中通過率比較高的題,STL 題和排序題也要去做,做到爛熟於心。
同時可以去LeetCode逛逛喲,做做簡單的題目~~對於編碼的基礎水平也有很大的提升哦!
乙級雖然報考的人數遠遠小於甲級(甲級永遠的神),但也還是指的一試的。這也算是對自己能力的肯定,而且乙級滿分也能收到offer哦!
總之,乙級 = 熟練模擬題 + STL + 邊界處理 + 細心 + 一些基礎數據結構的理解(鏈表、棧、隊列等等,沒有樹和圖,它們都在隔壁甲級~~全學總不會錯哈😜)