• Educational Codeforces Round 108 (Rated for Div. 2)【ABCD】


    五一快乐 (~ ̄▽ ̄)~

    比赛链接:https://codeforces.com/contest/1519

    A. Red and Blue Beans

    题意

    (r) 个红色豆子和 (b) 个蓝色豆子,需要将它们分成几包,要求每包:

    • 至少有一个红色豆子
    • 至少有一个蓝色豆子
    • 两种颜色豆子的数量之差不超过 (d)

    问能否将所有豆子分完 ?

    题解

    假设红色豆子比蓝色豆子少,为了尽可能地将蓝色豆子分完,每包应该放进 (1) 个红色豆子, (1 + d) 个蓝色豆子,否则无解。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int t;
        cin >> t;
        while (t--) {
            int r, b, d;
            cin >> r >> b >> d;
            if (r > b) {
                swap(r, b);
            }
            cout << (1LL * r * (d + 1) >= b ? "YES" : "NO") << "
    ";
        }
        return 0;
    }
    

    B. The Cake Is a Lie

    题意

    有一个 (n imes m) 的方阵,假设当前在 ((x, y)) 点,可以从以下两种移动操作中选择一种:

    • 向右移动到 ((x, y + 1)) ,花费为 (x)
    • 向下移动到 ((x + 1, y)) ,花费为 (y)

    起点为 ((1, 1)) ,问抵达终点 ((n, m)) 的花费能否刚好为 (k)

    题解

    花费只与起点与终点有关,与路径无关,即只需判断 (k) 是否等于从 ((1, 1))((n, m)) 的花费即可。

    证明

    假设有一个 (2 imes 2) 的方阵,从左上角 ((x, y)) 到右下角 ((x + 1, y + 1)) 显然只有两条路径,易得两条路径的花费均为 (x + y + 1)

    即,在一个 (2 imes 2) 方阵中,路径是可以关于主对角线翻折的。

    那么对于任意起点到任意终点间的任意路径,都可以利用路径中折角所在的 (2 imes 2) 方阵将路径翻折至同一种。

    ((1, 1))((n, m)) 最简单的路径即直右直下(或直下直右),花费即 ((m - 1) imes 1 + (n - 1) imes m = n imes m - 1)

    注:更完善的证明可以参考官方题解中的归纳证明法。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int t;
        cin >> t;
        while (t--) {
            int n, m, k;
            cin >> n >> m >> k;
            cout << (k == n * m - 1  ? "YES" : "NO") << "
    ";
        }
        return 0;
    }
    

    C. Berland Regional

    题意

    (n) 个学生,他们分别来自大学 (u_i) 并且编程能力为 (s_i)

    当队伍人数为 (k) 时,每个大学会以 (s_i) 为依据从大到小成 (k) 个将学生尽可能多地组队派出。

    问当 (k) 的值为 (1,2,...,n) 时,每次对应的所有队伍的编程能力之和为多少。

    题解

    对于学生人数为 (size) 的大学,当 (k > size) 时无法再派出队伍,所以该大学只需考虑 (k in [1, size]) 的情况。

    (k) 为某个值时,该大学的后 (size \% k) 个学生无法组队派出,即 (ans[k] mathrel{+}= s_0 + s_1 + dots + s_{size - 1 - (size \% k)}) ,多次对连续区间求和可以使用前缀和预处理。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int t;
        cin >> t;
        while (t--) {
            int n;
            cin >> n;
            vector<int> u(n);
            for (int i = 0; i < n; i++) {
                cin >> u[i];
                --u[i];
            }
            vector<int> s(n);
            for (int i = 0; i < n; i++) {
                cin >> s[i];
            }
            vector<vector<long long>> a(n);
            for (int i = 0; i < n; i++) {
                a[u[i]].push_back(s[i]);
            }
            vector<long long> ans(n + 1);
            for (auto vec : a) {
                sort(vec.begin(), vec.end(), greater<>());
                for (int i = 1; i < (int)vec.size(); i++) {
                    vec[i] += vec[i - 1];
                }
                for (int k = 1; k <= (int)vec.size(); k++) {
                    ans[k] += vec[(int)vec.size() - 1 - (int)vec.size() % k];
                }
            }
            for (int i = 1; i <= n; i++) {
                cout << ans[i] << " 
    "[i == n];
            }
        }
        return 0;
    }
    

    D. Maximum Sum of Products

    题意

    给出两个大小为 (n) 的数组 (a、b) ,最多可以反转一次 (a) 中的连续子数组,问 (sum_{i = 1}^{n} limits a_i cdot b_i) 的最大值。

    题解

    枚举中心点,依次向两边扩展。

    Tips

    注意连续子数组长度分奇偶两种情况。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        cin >> n;
        vector<long long> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        vector<long long> b(n);
        for (int i = 0; i < n; i++) {
            cin >> b[i];
        }
        long long ans = 0;
        for (int i = 0; i < n; i++) {
            ans += a[i] * b[i];
        }
        long long max_delta = 0;
        for (int i = 0; i < n; i++) {
            long long delta = 0;
            for (int l = i - 1, r = i + 1; l >= 0 and r < n; --l, ++r) {
                delta -= a[l] * b[l] + a[r] * b[r];
                delta += a[l] * b[r] + a[r] * b[l];
                max_delta = max(max_delta, delta);
            }
            delta = 0;
            for (int l = i, r = i + 1; l >= 0 and r < n; --l, ++r) {
                delta -= a[l] * b[l] + a[r] * b[r];
                delta += a[l] * b[r] + a[r] * b[l];
                max_delta = max(max_delta, delta);
            }
        }
        cout << ans + max_delta << "
    ";
        return 0;
    }
    
  • 相关阅读:
    玩转二叉树(二叉树的遍历)
    树的遍历(25分)
    树的遍历(25分)
    Java并发框架——AQS之怎样使用AQS构建同步器
    利用jsonrpc技术包装uiautomator
    HDU2059 龟兔赛跑 【DP】
    Android 利用WebViewJavascriptBridge 实现js和java的交互(一)
    玩转web之json(五)---将表单通过serialize()方法获取的值转成json
    网络暴力信号:你家的青少年是受害者或加害者吗?
    greenplum全量恢复gprecoverseg -F出现Unable to connect to database时的相关分析及解决方法
  • 原文地址:https://www.cnblogs.com/Kanoon/p/14724463.html
Copyright © 2020-2023  润新知