2019年9月 PAT甲级考试满分题解

整场回顾:

考前训练了不少,心情还是比较放松的,就告诉自己稳住心态,认真读题,不要钻牛角尖

开始考试,发现整体题目还好,没有很复杂,就开始从头看:A题发现意思很简单,但是不是很好想,想了一会大致有了个方向,因为A数字+1会产生较大变化,最后一位必然是9,然后我寻思这A题应该更简单,等等再看有没有更简单的做法。

然后看榜发现有俩哥们出了D题,然后出于自信我也直接去看D题,发现这场提很友好,题目都不难懂,C题树,D题图,没有恶心大模拟。看完D发现就是对于每个序列,跑一遍Dij,过程中检查序列是否合法,不合法直接退出;对PAT数据比较放心,D题也有1500ms的时限,所以我直接写的n²的Dij;(此时rank100+)

此时既然这样,那就倒着做C题吧,看完题,发现可以直接struct数组建树,直接莽了一发后序遍历,结果不对,看样例猜测,没有左子树的时候,直接输出根结点,其余情况还是后序遍历,很幸运交上过了(rank70+)。本以为这个题可能会凉了,考前想着看一下中缀后缀表达式的,结果正好没看也忘差不多了。

看榜发现还是BCD题出的多,寻思着这场有意思;

继续看B题,哎呀,这不类似天梯赛的一个题么:用struct数组储存链表结点,map映射首地址和数组中位置;说实话有点大意,写完样例都不过就夏98交了,后面各种调了一下才ok;(rank50+?)

只剩A题,感觉还是挺轻松的,就寻思着打个表看一下有没有规律把,打表方法:枚举A,若对应的n,m合法则输出。发现1e5以内的数最后两位好像都是9,然后有将表的范围调到1e7发现也没问题,这时候就稳了,最多9位数,定住了两位,就算递归枚举,也才1e7的复杂度,再说还可以剪枝啥的,然后直接暴力写了(懒得找简单方法了,流氓就流氓把2333)。后面没看见顺序输出,调了会,不太怀疑99规律不对,就重新读了遍题,改了一下就ok了(rank1=23)

 

A题:

#include<bits/stdc++.h>
#define FI first
#define SE second

using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int maxn = 10 + 777;

int k, m;
int a[maxn];
bool okk = false;
set<P> ans;

int num(int n) {
    int res = 0;
    while(n) {
        res += (n % 10);
        n /= 10;
    }
    return res;
}
bool isp(int n) {
    if(n == 0 || n == 1) return false;
    for(int i = 2; i*i <= n; ++i) {
        if(n%i == 0) return false;
    }
    return true;
}
bool ok() {
    int n = 0;
    for(int i = 1; i <= k; ++i) {
        n = n*10 + a[i];
    }
    //cout << n << endl;
    int t1 = num(n);
    if(t1 != m) return false;
    int t2 = num(n+1);
    int t = __gcd(t1, t2);
    if(t > 2 && isp(t)){
        ans.insert(P(t2, n));
        //printf("%d %d\n", t2, n);
        return true;
    }
    return false;
}
int sum(int t) {
    int res = 0;
    for(int i = 1; i <= t; ++i) {
        res += a[i];
    }
    return res;
}
void work(int cnt) {
    //cout << cnt << endl;
    if(cnt == k-1) {
        if(ok()) {
            okk = true;
        }
        return;
    }
    for(int i = 0; i <= 9; ++i) {
        if(i == 0 && cnt == 1) continue;
        a[cnt] = i;
        if(sum(cnt) > (m-18)) break;
        work(cnt+1);
    }
    return;
}
void solve() {
    scanf("%d%d", &k, &m);
    a[k-1] = a[k] = 9;
    okk = false;
    ans.clear();
    work(1);
    for(auto i : ans) {
        printf("%d %d\n", i.FI, i.SE);
    }
    if(!okk)
        puts("No Solution");
    return;
}
int main() {
    int T; scanf("%d", &T);
    for(int i = 1; i <= T; ++i) {
        printf("Case %d\n", i);
        solve();
    }

    return 0;
}

 

B题:

#include<bits/stdc++.h>
#define FI first
#define SE second

using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int maxn = 1e5 + 777;

int n;
struct node {
    string s, t;
    int v;
}a[maxn];
map<string, int> mp;
string s1, s2;

int find_(string s) {
    int t = mp[s];
    int res = 0;
    while(t != -1) {
        res++;
        t = mp[a[t].t];
    }
    return res;
}
void solve() {
    int t1 = mp[s1];
    int t2 = mp[s2];
    vector<int> tmp;
    while(t2 != -1) {
        tmp.push_back(t2);
        t2 = mp[a[t2].t];
    }
    t2 = tmp.size()-1;
    while(1) {
        cout << a[t1].s << " " << a[t1].v << " " << a[t1].t << endl;
        t1 = mp[a[t1].t];
        cout << a[t1].s << " " << a[t1].v << " " << a[tmp[t2]].s << endl;
        t1 = mp[a[t1].t];
        if(t1 == -1) {
            cout << a[tmp[t2]].s << " " << a[tmp[t2]].v << " " << -1 << endl;
            break;
        }
        else {
            cout << a[tmp[t2]].s << " " << a[tmp[t2]].v << " " << a[t1].s << endl;
            t2--;
            if(t2 == -1) {
                while(t1 != -1) {
                    cout << a[t1].s << " " << a[t1].v << " " << a[t1].t << endl;
                    t1 = mp[a[t1].t];
                }
                break;
            }
        }
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >>s1 >> s2 >> n;
    mp["-1"] = -1;
    for(int i = 1; i <= n; ++i) {
        cin >> a[i].s >> a[i].v >> a[i].t;
        mp[a[i].s] = i;
    }
    int t1 = find_(s1);
    int t2 = find_(s2);
    if(t1 < t2) swap(s1, s2);
    solve();
    return 0;
}

 

C题:

#include<bits/stdc++.h>
#define FI first
#define SE second

using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int maxn = 1e6 + 777;
const int INF = 0x3f3f3f3f;
int n, u;
bool vis[maxn];
struct node {
    string s;
    int l ,r;
}a[maxn];
void solve(int id) {
    if(id == -1) return;
    printf("(");
    solve(a[id].l);
    if(a[id].l == -1) cout << a[id].s;
    solve(a[id].r);
    if(a[id].l != -1) cout << a[id].s;
    printf(")");
}
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        cin >> a[i].s >>a[i].l >> a[i].r;
        vis[a[i].l] = 1;
        vis[a[i].r] = 1;
    }
    u = -1;
    for(int i = 1; i <= n; ++i) {
        if(!vis[i]) {
            u = i;
            break;
        }
    }
    solve(u);
    return 0;
}

 

D题:

#include<bits/stdc++.h>
#define FI first
#define SE second

using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int maxn = 1e3 + 7;
const int INF = 0x3f3f3f3f;

int n, m;
vector<P> vec[maxn];
int a[maxn];
int d[maxn];
bool vis[maxn];

void solve() {
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    memset(d, INF, sizeof d);
    memset(vis, 0, sizeof vis);
    d[a[1]] = 0;
    for(auto i : vec[a[1]]) {
        d[i.FI] = i.SE;
    }
    int idd = 1;
    while(1) {
        int t = -1;
        for(int i = 1; i <= n; ++i) {
            if(!vis[i] && (t == -1 || d[t] > d[i])) t = i;
        }
        if(t == -1) break;
        int x = a[idd];
        if(d[x] != d[t]) {
            puts("No");
            return;
        }
        t = x;
        vis[t] = 1;
        for(auto i : vec[t]) {
            d[i.FI] = min(d[i.FI], d[t] + i.SE);
        }
        idd++;
    }
    puts("Yes");
    return;
}
int main() {
    scanf("%d%d", &n, &m);
    int u, v, w;
    for(int i = 1; i <= m; ++i) {
        scanf("%d%d%d", &u, &v, &w);
        vec[u].push_back(P(v, w));
        vec[v].push_back(P(u, w));
    }
    int k; scanf("%d", &k);
    for(int i = 1; i <= k; ++i) {
        solve();
    }
    return 0;
}

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值