PAT(乙级)2020年春季考试真题解析


七夕了呀,那就刷题吧~~~
本次试题依旧使用 C++ 进行求解~

由于疫情原因,本次PAT由原来的线下举办改为线上考试9月份还有一场,想参加的小伙伴不要错过呀

由于本人过菜,这次七夕教超打折依旧只敢去做做乙级题(截至目前已售出30份)~😂

废话不多说,开冲!

PAT(乙级)2020年春季考试直达链接:这里

试题集の基本情况

对称日(15分)

思路

  1. 需要处理输入的 date
    • 将月份应为简写转换为对应的数字
    • 将年日月按要求组合起来
  2. 检验是否为对称日
    • 可以转换为字符串,按对应的位或者反转进行对比
    • 可以将月份与日期的和(月份 * 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 + 边界处理 + 细心 + 一些基础数据结构的理解(链表、栈、队列等等,没有树和图,它们都在隔壁甲级~~全学总不会错哈😜)


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM