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;
}
原文地址:https://www.cnblogs.com/Kanoon/p/14724463.html