• AtCoder Beginner Contest 212【A


    比赛链接:https://atcoder.jp/contests/abc212/tasks

    A - Alloy

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int a, b;
        cin >> a >> b;
        if (a > 0 and b > 0) {
            cout << "Alloy" << "
    ";
        } else if (a > 0) {
            cout << "Gold" << "
    ";
        } else {
            cout << "Silver" << "
    ";
        }
        return 0;
    }
    

    B - Weak Password

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        string s;
        cin >> s;
        string t;    
        for (int i = 1; i < 4; i++) {
            t += '0' + (s[i] - s[i - 1] + 10) % 10;
        }
        cout << (t == "000" or t == "111" ? "Weak" : "Strong") << "
    ";
        return 0;
    }
    

    C - Min Difference

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, m;
        cin >> n >> m;
        set<int> a, b;
        for (int i = 0; i < n; i++) {
            int x;
            cin >> x;
            a.insert(x);
        }
        for (int i = 0; i < m; i++) {
            int x;
            cin >> x;
            b.insert(x);
        }
        int ans = INT_MAX;
        for (auto i : a) {
            auto it = b.lower_bound(i);
            ans = min(ans, abs(*it - i));
            if (it != b.begin()) {
                ans = min(ans, abs(*prev(it) - i));
            }
        }
        cout << ans << "
    ";
        return 0;
    }
    

    D - Querying Multiset

    题解

    考虑相对大小。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int q;
        cin >> q;
        priority_queue<long long, vector<long long>, greater<long long>> pque;
        long long delta = 0;
        while (q--) {
            int op;
            cin >> op;
            if (op == 1) {
                int x;
                cin >> x;
                pque.push(x - delta);
            } else if (op == 2) {
                int x;
                cin >> x;
                delta += x;
            } else {
                cout << pque.top() + delta << "
    ";
                pque.pop();
            }
        }
        return 0;
    }
    

    E - Safety Journey

    题意

    从一个含有 (n)​​​ 个结点的完全图中去掉 (m)​​ 条边,问长为 (k) ,且起点和终点均为结点 (1)​ 的路径个数。

    题解

    由数据范围猜测应为二维 (dp)​ ,设 (dp_{ij})​ 为从起点出发,长为 (i)​ ,终点为 (j)​​ 的路径个数。

    易得状态转移方程为:

    vector<vector<int>> dp(k + 1, vector<int> (n));
    dp[0][0] = 1; // 初始状态,长为 0 ,从结点 1 出发
    for (int i = 0; i < k; i++) {
        for (int u = 0; u < n; u++) { // 枚举下一层路径长度的终点
            for (auto v : G[u]) { // 所有与终点相连的结点都可以转移到该点并使路径长度加一
                dp[i + 1][u] += dp[i][v];
            }
        }
    }
    cout << dp[k][0] << "
    ";
    

    由于边界情况余下边数较多,内两层的循环次数多达 (10^6)​​ ,所以不妨考虑不用加法,而是用减法得到下一层的结果。

    类比一下就是:

    a + b + c + d = e
    ans = a + b + c // 为某一终点加上所有与之相邻结点的方案数
    ans = e - d // 从总方案数中减去所有与该终点不相邻的结点的方案数
    

    状态转移方程为:

    vector<vector<int>> dp(k + 1, vector<int> (n));
    dp[0][0] = 1;
    for (int i = 0; i < k; i++) {
        int sum = accumulate(dp[i].begin(), dp[i].end(), 0);
        for (int u = 0; u < n; u++) {
            dp[i + 1][u] = sum;
            for (auto v : G[u]) {
                dp[i + 1][u] -= dp[i][v];
            }
        }
    }
    cout << dp[k][0] << "
    ";
    

    最后可以压缩一下空间复杂度。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    constexpr int MOD = 998244353;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, m, k;
        cin >> n >> m >> k;
        vector<vector<int>> G(n);
        for (int u = 0; u < n; u++) {
            G[u].push_back(u);
        }
        for (int i = 0; i < m; i++) {
            int u, v;
            cin >> u >> v;
            --u, --v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        vector<int> dp(n);
        dp[0] = 1;
        for (int i = 0; i < k; i++) {
            int sum = accumulate(dp.begin(), dp.end(), 0, [&](int x, int sum) { return (x + sum) % MOD; });
            vector<int> next_dp(n);
            for (int u = 0; u < n; u++) {
                next_dp[u] = sum;
                for (auto v : G[u]) {
                    next_dp[u] = (next_dp[u] - dp[v] + MOD) % MOD;
                }
            }
            dp = next_dp;
        }
        cout << dp[0] << "
    ";
        return 0;
    }
    

    参考

    https://atcoder.jp/contests/abc212/submissions/24652558

  • 相关阅读:
    常用的字符串内建函数(三)
    常用的字符串内建函数(二)
    常用的字符串内建函数(一)
    Python 运算符
    Python标准数据类型--数字类型
    HTTPS及免费证书获取
    try...catch...finally
    加密和SSH认证
    全表更新锁表
    秩和比
  • 原文地址:https://www.cnblogs.com/Kanoon/p/15085814.html
Copyright © 2020-2023  润新知