• AtCoder Beginner Contest 203(Sponsored by Panasonic)


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

    A - Chinchirorin

    题意

    给出三个数,如果有两个数相同,输出剩下的那个数。

    题解

    模拟。

    代码

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

    B - AtCoder Condominium

    题意

    一栋公寓有 (n) 层,每层有 (k) 个房间,第 (i) 层第 (j) 间房间号为 (i0j) ,计算所有房间号之和。

    题解

    模拟。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, k;
        cin >> n >> k;
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= k; j++) {
                ans += i * 100 + j;
            }
        }
        cout << ans << "
    ";
        return 0;
    }
    

    C - Friends and Travel costs

    题意

    有无穷多个村庄,开始时 Taro 在村庄 (0) ,他可以花费 (1) 元从村庄 (i) 移动到村庄 (i + 1)

    Taro 有 (n) 个朋友,给出他们所在的村庄 (a_i) 和 Taro 到达他们村庄时他们给 Taro 的钱数 (b_i) ,计算 Taro 最远可以到达的村庄。

    题解

    模拟。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        long long n, k;
        cin >> n >> k;
        vector<pair<long long, int>> v(n);
        for (int i = 0; i < n; i++) {
            cin >> v[i].first >> v[i].second;
        }
        sort(v.begin(), v.end());
        for (auto [x, y] : v) {
            if (k >= x) {
                k += y;
            } else {
                break;
            }
        }
        cout << k << "
    ";
        return 0;
    }
    

    D - Pond

    题意

    给出一个 (n) 阶方阵,计算所有 (k) 阶方阵的中位数的最小值。

    这里 (k) 阶方阵的中位数为: (k^2) 个数中第 (lfloor frac{k^2}{2} floor + 1) 个大的数。

    题解

    二分中位数的值,将大于二分值的数记为 (1) ,小于等于的记为 (0) ,作二维前缀和来枚举所有 (k) 阶方阵。

    如果存在一个方阵满足其和小于等于 (lfloor frac{k^2}{2} floor) ,则当前二分值可行,设为上界,否则设为下界。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, k;
        cin >> n >> k;
        vector<vector<int>> a(n + 1, vector<int> (n + 1));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cin >> a[i][j];
            }
        }
        int l = 0, r = 1e9, ans = 0;
        while (l <= r) {
            int mid = (l + r) / 2;
            vector<vector<int>> pref_sum(n + 1, vector<int> (n + 1));
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    pref_sum[i][j] = pref_sum[i - 1][j] + pref_sum[i][j - 1] - pref_sum[i - 1][j - 1] + (a[i - 1][j - 1] > mid);
                }
            }
            bool possible = false;
            for (int i = k; i <= n; i++) {
                for (int j = k; j <= n; j++) {
                    if (pref_sum[i][j] - pref_sum[i - k][j] - pref_sum[i][j - k] + pref_sum[i - k][j - k] <= k * k / 2) {
                        possible = true;
                    }
                }
            }
            if (possible) {
                ans = mid;
                r = mid - 1;
            } else {
                l = mid + 1;
            }
        }
        cout << ans << "
    ";
        return 0;
    }
    

    E - White Pawn

    题意

    给出 ((2n + 1) imes (2n + 1)) 的棋盘上 (m) 枚黑子的坐标,开始时一枚白子在 ((0, n)) 处,白子的移动策略如下:

    • ((i + 1, j)) 没有黑子,则可以移动到 ((i + 1, j))
    • ((i + 1, j - 1)) 有黑子,则可以移动到 ((i + 1, j - 1))
    • ((i + 1, j + 1)) 有黑子,则可以移动到 ((i + 1, j + 1))

    问白子可能到达第 (2n) 行的哪些坐标。

    题解

    如果遇到空行白子只能往下移,即空行不影响纵坐标的变化。

    所以从上往下依次枚举有黑子的行即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, m;
        cin >> n >> m;
        map<int, vector<int>> mp;
        for (int i = 0; i < m; i++) {
            int x, y;
            cin >> x >> y;
            mp[x].push_back(y);
        }
        set<int> prev_row{n};
        for (auto [x, vec_y] : mp) {
            vector<int> next_row;
            for (auto y : vec_y) {
                for (auto d : {-1, 1}) {
                    if (prev_row.count(y + d)) {
                        next_row.push_back(y);
                    }
                }
            }
            for (auto y : vec_y) {
                prev_row.erase(y);
            }
            for (auto y : next_row) {
                prev_row.insert(y);
            }
        }
        cout << prev_row.size() << "
    ";
        return 0;
    }
    

    F - Weed

    题意

    花园里有 (n) 株野草,Takahashi 和 Aoki 打算按如下方案拔掉这些野草:

    • Aoki 先拔掉最多 (k) 株野草
    • 之后 Takahashi 重复如下操作:
      • 假设 (h) 为余下野草中的最大高度,拔掉所有高度大于 (lfloor frac{h}{2} floor) 的野草

    问在 Takahashi 操作最少次的情况下, Aoki 最少要拔掉多少株野草。

    题解

    (dp_{ij}) 为前 (i) 株野草 Takahashi 操作 (j) 次时 Aoki 要拔掉多少株。

    • 若第 (i) 株由 Aoki 拔掉,那么有状态转移方程:

      • (dp_{ij} = min(dp_{ij}, dp_{i - 1j} + 1))
    • 若第 (i) 株由 Takahashi 拔掉,由于其操作的特殊性,假设此时还剩 (x) 株,那么有状态转移方程:

      • (dp_{ij+1} = min(dp_{ij+1}, dp_{xj})) ,即 Aoki 无需再对 ([x + 1, i]) 间的野草进行任何操作。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, k;
        cin >> n >> k;
        vector<int> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        sort(a.begin(), a.end());
        const int m = 32;
        const int INF = n;
        vector<vector<int>> dp(n + 1, vector<int> (m, INF));
        dp[0][0] = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < m; j++) {
                dp[i][j] = min(dp[i][j], dp[i - 1][j] + 1);
            }
            int x = upper_bound(a.begin(), a.end(), a[i - 1] / 2) - a.begin();
            for (int j = 0; j + 1 < m; j++) {
                dp[i][j + 1] = min(dp[i][j + 1], dp[x][j]);
            }
        }
        for (int i = 0; i < m; i++) {
            if (dp[n][i] > k) {
                continue;
            }
            cout << i << ' ' << dp[n][i] << "
    ";
            break;
        }
        return 0;
    }
    
  • 相关阅读:
    大整数乘法
    Independent Components Analysis:独立成分分析
    因子分析(Factor analysis)
    EM算法原理详解
    简易解说拉格朗日对偶(Lagrange duality)
    机器学习中有关概率论知识的小结
    高斯混合和EM算法
    java
    java
    java
  • 原文地址:https://www.cnblogs.com/Kanoon/p/14838247.html
Copyright © 2020-2023  润新知