• AtCoder Beginner Contest 215【A


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

    A - Your First Judge

    题意

    如果一个字符串是 Hello,World! ,输出 AC ,否则输出 WA

    题解

    模拟。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        string s;
        cin >> s;
        cout << (s == "Hello,World!" ? "AC" : "WA") << "
    ";
        return 0;
    }
    

    B - log2(N)

    题意

    输出 (2) 不超过 (n) 的最大幂次方。

    题解

    模拟。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        long long n;
        cin >> n;
        cout << __lg(n) << "
    ";
        return 0;
    }
    

    C - One More aab aba baa

    题意

    给出一个字符串,输出其所含有的字母对应的字典序第 (k) 小的字符串。

    题解

    模拟。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        string s;
        int k;
        cin >> s >> k;
        sort(s.begin(), s.end());
        int cnt = 0;
        do {
            if (++cnt == k) {
                cout << s << "
    ";
                break;
            }
        } while (next_permutation(s.begin(), s.end()));
        return 0;
    }
    

    D - Coprime 2

    题意

    给出一个大小为 (n) 的数组 (a) ,找出 ([1, m]) 中与每个 (a_i)(gcd=1) 的数。

    题解

    把每个 (a_i) 做一下质因子分解然后用这些质因子筛一下 ([1, m]) 即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    constexpr int N = 1e5 + 10;
    
    int p[N];
    void Init() {
        for (int i = 2; i < N; i++) {
            if (p[i]) {
                continue;
            }
            for (int j = i; j < N; j += i) {
                p[j] = i;
            }
        }
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        Init();
        int n, m;
        cin >> n >> m;
        vector<int> a(n);
        set<int> st;
        for (int i = 0; i < n; i++) {
            cin >> a[i];
            for (int j = a[i]; j != 1; j /= p[j]) {
                st.insert(p[j]);
            }
        }
        vector<bool> is(N, true);
        for (auto i : st) {
            if (not is[i] or i == 1) {
                continue;
            }
            for (int j = i; j < N; j += i) {
                is[j] = false;
            }
        }
        vector<int> ans;
        for (int i = 1; i <= m; i++) {
            if (is[i]) {
                ans.push_back(i);
            }
        }
        cout << ans.size() << "
    ";
        for (auto i : ans) {
            cout << i << "
    ";
        }
        return 0;
    }
    

    E - Chain Contestant

    题意

    给出一个长为 (n) 的字符串 (s) ,计算共有多少子序列满足相同字母在原串中连续。

    题解

    将字符逐个考虑,每次它需要加上之前所有不含它或以它结尾的序列。

    模拟代码即:

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        string s;
        cin >> n >> s;
        map<string, int> mp;
        mp[""] = 1;
        for (auto ch : s) {
            auto next_mp(mp);
            for (auto [x, y] : mp) {
                if (x.find(ch) == string::npos) {
                    next_mp[x + ch] += mp[x];
                } else if (x.back() == ch) {
                    next_mp[x] += mp[x];
                }
            }
            mp = next_mp;
        }
        int ans = 0;
        for (auto [x, y] : mp) {
            if (x != "") {
                ans += y;
            }
        }
        cout << ans << "
    ";
        return 0;
    }
    

    但最多有 (2^{|s| = 1000}) 种子序列,考虑利用题目条件压缩。

    因为最多有 (10) 个字母,所以可以枚举字母的所有排列组合方式,同时连续的相同字母都可以看作一个字母,所以最终共可能有 (sum limits _{i = 1}^{10} C_{10}^i cdot A_i^i approx 10^7) 种序列。

    (|s| cdot 10^7 = 10^{10}) 的复杂度仍难以接受(事实上这份代码跑了 (20s) ),考虑进一步压缩。

    因为只需要知道一个序列是否含有 (ch) 或以 (ch) 结尾,所以可以只保存序列的字母集和结尾字母,此时复杂度为 (|s| cdot 2^{10} cdot 10 approx 10^7)

    (dp_{ij}) 为字母集为 (i) ,以字母 (j) 结尾的序列个数,将上部分代码改写一下即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    constexpr int N = 1 << 10;
    constexpr int MOD = 998244353;
    
    int norm(int x) { if (x < 0) { x += MOD; } if (x >= MOD) { x -= MOD; } return x; }
    template<class T> T binpow(T a, int b) { T res = 1; for (; b; b /= 2, a *= a) { if (b % 2) { res *= a; } } return res; }
    
    struct Z {
        int x;
        Z(int x = 0) : x(norm(x)) {}
        int val() const { return x; }
        Z operator-() const { return Z(norm(MOD - x)); }
        Z inv() const { assert(x != 0); return binpow(*this, MOD - 2); }
        Z &operator*=(const Z &rhs) { x = 1LL * x * rhs.x % MOD; return *this; }
        Z &operator+=(const Z &rhs) { x = norm(x + rhs.x); return *this; }
        Z &operator-=(const Z &rhs) { x = norm(x - rhs.x); return *this; }
        Z &operator/=(const Z &rhs) { return *this *= rhs.inv(); }
        friend Z operator*(const Z &lhs, const Z &rhs) { Z res = lhs; res *= rhs; return res; }
        friend Z operator+(const Z &lhs, const Z &rhs) { Z res = lhs; res += rhs; return res; }
        friend Z operator-(const Z &lhs, const Z &rhs) { Z res = lhs; res -= rhs; return res; }
        friend Z operator/(const Z &lhs, const Z &rhs) { Z res = lhs; res /= rhs; return res; }
    };
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        string s;
        cin >> n >> s;
        vector<vector<Z>> dp(N, vector<Z> (10));
        for (auto ch : s) {
            auto next_dp(dp);
            int id = ch - 'A';
            for (int i = 0; i < N; i++) {
                if ((i & (1 << id)) == 0) {
                    next_dp[i | (1 << id)][id] += (i == 0 ? 1 : accumulate(dp[i].begin(), dp[i].end(), Z(0)));
                } else {
                    next_dp[i][id] += dp[i][id];
                }
            }
            dp = next_dp;
        }
        Z ans = 0;
        for (auto vec : dp) {
            for (auto x : vec) {
                ans += x;
            }
        }
        cout << ans.val() << "
    ";
        return 0;
    }
    

    F - Dist Max 2

    题意

    给出平面上的 (n) 个整数点,定义两点间的距离为 (mathrm{min} (|x_i-x_j|,|y_i-y_j|)) ,找出两个不同点间的最大距离。

    题解

    The maximization problem of a minimum value can often be solved with a binary search.

    ——Editorial

    考虑二分最终答案,将所有点按 (x) 坐标从小到大排序,然后记录满足 (x - pre_x ge mid)(pre_y) 的最值,若存在 (y - pre_{y\_{min}})(pre_{y\_{max}} - y ge mid) ,则该二分值可行,设为下界。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        cin >> n;
        vector<pair<int, int>> a(n);
        for (auto& [x, y] : a) {
            cin >> x >> y;
        }
        sort(a.begin(), a.end());
        int l = 0, r = 1e9;
        while (l < r) {
            int mid = (l + r + 1) / 2;
            bool ok = false;
            queue<pair<int, int>> que; 
            int mi = 1e9, mx = 0;
            for (auto [x, y] : a) {
                while (not que.empty() and x - que.front().first >= mid) {
                    mi = min(mi, que.front().second);
                    mx = max(mx, que.front().second);
                    que.pop();
                }
                if (y - mi >= mid or mx - y >= mid) {
                    ok = true;
                }
                que.emplace(x, y);
            }
            if (ok) {
                l = mid;
            } else {
                r = mid - 1;
            }
        }
        cout << l << "
    ";
        return 0;
    }
    

    G - Colorful Candies 2

    题意

    (n) 个带颜色的糖果,计算当 (k = 1, 2, dots, n) 时, (C_{n}^{k}) 种情况中糖果颜色数的期望。

    题解

    出现 (c_i) 次的颜色对总期望的贡献为 (1 imes frac{C_n^k - C_{n - c_i}^k}{C_n^k})

    但逐颜色计算时间复杂度为 (O_{(n^2)}) ,考虑进行压缩:对于有相同出现次数 (c_i) 的颜色,可以合并计算为 (tot imes frac{C_n^k - C_{n - c_i}^k}{C_n^k}) ,此时时间复杂度为 (O_{(n sqrt{n})})

    证明

    假设出现次数都不相同,因为 (sum c_i = n = 1 + 2 + dots +m) ,即 (frac{m(m + 1)}{2} = n) ,易得 (m le sqrt{n}) ,所以此时时间复杂度为 (O_{(n sqrt{n})})

    代码

    #include <bits/stdc++.h>
    using namespace std;
    constexpr int MOD = 998244353;
    
    int norm(int x) { if (x < 0) { x += MOD; } if (x >= MOD) { x -= MOD; } return x; }
    template<class T> T binpow(T a, int b) { T res = 1; for (; b; b /= 2, a *= a) { if (b % 2) { res *= a; } } return res; }
    
    struct Z {
        int x;
        Z(int x = 0) : x(norm(x)) {}
        int val() const { return x; }
        Z operator-() const { return Z(norm(MOD - x)); }
        Z inv() const { assert(x != 0); return binpow(*this, MOD - 2); }
        Z &operator*=(const Z &rhs) { x = 1LL * x * rhs.x % MOD; return *this; }
        Z &operator+=(const Z &rhs) { x = norm(x + rhs.x); return *this; }
        Z &operator-=(const Z &rhs) { x = norm(x - rhs.x); return *this; }
        Z &operator/=(const Z &rhs) { return *this *= rhs.inv(); }
        friend Z operator*(const Z &lhs, const Z &rhs) { Z res = lhs; res *= rhs; return res; }
        friend Z operator+(const Z &lhs, const Z &rhs) { Z res = lhs; res += rhs; return res; }
        friend Z operator-(const Z &lhs, const Z &rhs) { Z res = lhs; res -= rhs; return res; }
        friend Z operator/(const Z &lhs, const Z &rhs) { Z res = lhs; res /= rhs; return res; }
    };
    
    struct comb {
        vector<Z> fac, inv;
    
        comb(int n) : fac(n), inv(n) {
            fac[0] = 1;
            for (int i = 1; i < n; i++) fac[i] = fac[i - 1] * i;
            inv[n - 1] = fac[n - 1].inv();
            for (int i = n - 2; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1);
        }
    
        Z C(int n, int m){
            if(m < 0 or m > n) return 0;
            return fac[n] * inv[m] * inv[n - m];
        }
    };
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        cin >> n;
        vector<int> c(n);
        for (int i = 0; i < n; i++) {
            cin >> c[i];
        }
        auto disc = [](vector<int> res) {
            vector<int> a(res);
            sort(a.begin(), a.end());
            a.resize(unique(a.begin(), a.end()) - a.begin());
            for (auto& i : res) {
                i = lower_bound(a.begin(), a.end(), i) - a.begin();
            }
            return res;
        };
        auto zip = [](vector<int> c, int n) {
            vector<int> color(c.size());
            for (auto i : c) {
                ++color[i];
            }
            vector<int> tot(n + 1);
            for (auto i : color) {
                ++tot[i];
            }
            vector<pair<int, int>> res;
            for (int i = 1; i <= n; i++) {
                if (tot[i]) {
                    res.emplace_back(tot[i], i);
                }
            }
            return res;    
        };
        vector<pair<int, int>> v = zip(disc(c), n);
        comb comb(n + 1);
        for (int k = 1; k <= n; k++) {
            Z ans = 0;
            for (auto [tot, c_i] : v) {
                ans += tot * (comb.C(n, k) - comb.C(n - c_i, k)) * comb.C(n, k).inv();
            }
            cout << ans.val() << "
    ";
        }
        return 0;
    }
    

    参考

    https://atcoder.jp/contests/abc215/editorial/2514

    https://atcoder.jp/contests/abc215/editorial/2515

    https://atcoder.jp/contests/abc215/editorial/2516

  • 相关阅读:
    再谈iOS 7的手势滑动返回功能
    CGContextRef用法
    UIView的layoutSubviews和drawRect方法何时调用
    layoutSubviews何时调用的问题
    iOS应用开发最佳实践:编写高质量的Objective-C代码
    WWDC2014之App Extensions学习笔记
    定制iOS 7中的导航栏和状态栏
    从客户端中检测到有潜在危险的 Request.Form 值
    async and await 简单的入门
    C# Dictionary学习
  • 原文地址:https://www.cnblogs.com/Kanoon/p/15171119.html
Copyright © 2020-2023  润新知