码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2021-05-03 12:59:22      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:rate   ted   红色   ati   官方   div   com   i++   span   

大家五一快乐呀 (~ ̄▽ ̄)~

比赛链接: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") << "\n";
    }
    return 0;
}

B. The Cake Is a Lie

题意

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

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

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

题解

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

证明

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

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

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

\((1, 1)\)\((n, m)\) 最简单的路径即直右直下(或直下直右),花费即 \((m - 1) \times 1 + (n - 1) \times m = n \times 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") << "\n";
    }
    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] << " \n"[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 << "\n";
    return 0;
}

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

标签:rate   ted   红色   ati   官方   div   com   i++   span   

原文地址:https://www.cnblogs.com/Kanoon/p/14724463.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!