Codeforces Round #680 (Div. 2, based on Moscow Team Olympiad)【ABCD】

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

A. Array Rearrangment

题意

给定两个大小均为 \(n\) 的升序数组 \(a\)\(b\) ,判断能否重排数组 \(b\) 使得对任意 \(i\) 均满足 \(a_i + b_i \le x\)

题解一

因为 \(a\) 为升序,所以将 \(b\) 按照降序排列判断即可。

代码

#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, x;
        cin >> n >> x;
        vector<int> a(n);
        for (auto &x : a) cin >> x;
        vector<int> b(n);
        for (auto &x : b) cin >> x;
        sort(b.begin(), b.end(), greater<>());
        bool ok = true;
        for (int i = 0; i < n; i++) if (a[i] + b[i] > x) ok = false;
        cout << (ok ? "Yes" : "No") << "\n";
    }
    return 0;
}

题解二

\(a\) 不以升降序给出,则需要对 \(a\) 中的每个数在 \(b\) 中贪心查找最匹配的数。

代码

#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, x;
        cin >> n >> x;
        vector<int> a(n);
        for (auto &x : a) cin >> x;
        multiset<int> st;
        for (int i = 0; i < n; i++) {
            int x;
            cin >> x;
            st.insert(x);
        }
        for (const auto &i : a) {
            auto it = st.upper_bound(x - i);
            if (it != st.begin() and *prev(it) <= x - i) st.erase(prev(it));
        }
        cout << (st.size() == 0 ? "Yes" : "No") << "\n";
    }
    return 0;
}

B. Elimination

题意

决赛之前有两场选拔赛,已知:

  • 第一场选拔赛第 \(100\) 名的分数为 \(a\) ,第二场选拔赛所有人的分数都不少于 \(b\)
  • 第二场选拔赛第 \(100\) 名的分数为 \(c\) ,第一场选拔赛所有人的分数都不少于 \(d\)

计算两场选拔赛的总分至少要多少才能进入决赛。

题解

假如刚好有两百人,那么可以进行以下合理假设:

  • 第一场前一百名分数为 \(a\) ,后一百名分数为 \(b\)
  • 第二场前一百名分数为 \(c\) ,后一百名分数为 \(d\)
  • 第二场的前一百名刚好为第一场的后一百名
  • 第二场的后一百名刚好为第一场的前一百名

那么答案即 \(max(a + b,\ c + 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 a, b, c, d;
        cin >> a >> b >> c >> d;
        cout << max(a + b, c + d) << "\n";
    }
    return 0;
}

C. Division

题意

给定两个数 \(a\)\(b\) ,计算满足以下条件的 \(x\) 的最大值:

  • \(x\)\(a\) 的因子
  • \(x\) 不是 \(b\) 的倍数

题解

最理想的 \(x\)\(a\) 本身,此时如果 \(x\)\(b\) 的倍数,那么只要将 \(x\) 内的某一质因子降到 \(b\) 中的幂次以下即可。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        long long a, b;
        cin >> a >> b;
        vector<int> p;
        long long n = b;
        for (int i = 2; i * i <= n; i++) {
            if (n % i == 0) {
                p.push_back(i);
                while (n % i == 0) n /= i;
            }
        }
        if (n > 1) p.push_back(n);
        long long ans = 1;
        for (auto i : p) {
            long long res = a;
            while (res % b == 0) res /= i;
            ans = max(ans, res);
        }
        cout << ans << "\n";
    }
    return 0;
}

D. Divide and Sum

题意

给定一个大小为 \(2n\) 的数组,考虑将其拆分为两个等长的子序列 \(p\)\(q\) ,并将 \(p\) 以升序排列, \(q\) 以降序排列,同时定义 \(f(p, q) = \sum_{i = 1}^n |p_i - q_i|\)
计算所有可能子序列情况下的 \(f(p, q)\) 之和。

题解

不管怎么分,都是大的一半减去小的一半,将和记为 \(sum\) ,答案即 \(C_{2n}^n \times sum\)

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int N = 1e6 + 100;
constexpr int MOD = 998244353;

int fac[N], inv[N];

int binpow(int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1) res = 1LL * res * a % MOD;
        a = 1LL * a * a % MOD;
        b >>= 1;
    }
    return res;
}

int C(int n, int m){
    if(m < 0 or m > n) return 0;
    return 1LL * fac[n] * inv[m] % MOD * inv[n - m] % MOD;
}

void Init(){
    fac[0] = 1;
    for (int i = 1; i < N; i++) fac[i] = 1LL * fac[i - 1] * i % MOD;
    inv[N - 1] = binpow(fac[N - 1], MOD - 2);
    for (int i = N - 2; i >= 0; i--) inv[i] = 1LL * inv[i + 1] * (i + 1) % MOD;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    Init();
    int n;
    cin >> n;
    n *= 2;
    vector<int> a(n);
    for (auto &x : a) cin >> x;
    sort(a.begin(), a.end());
    int sum = 0;
    for (int i = 0; i < n / 2; i++) {
        sum += abs(a[i] - a[n - 1 - i]);
        sum %= MOD;
    }
    cout << C(n, n / 2) * sum % MOD << "\n";
    return 0;
}

posted @ 2020-11-04 11:30  Kanoon  阅读(151)  评论(0编辑  收藏  举报