Codeforces Round #570 (Div. 3)

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

A - Nearest Interesting Number

题意

寻找不小于 $a$ 的最小的数位之和为 $4$ 的倍数的数。(1 ≤ a ≤ 1000)

代码

#include <bits/stdc++.h>
using namespace std;

int sum(int n) {
    int res = 0;
    while (n) {
        res += n % 10;
        n /= 10;
    }
    return res;
}

int main() {
    int a; cin >> a;
    for (int i = a; i <= 1003; i++) {
        if (sum(i) % 4 == 0) {
            cout << i;
            break;
        }
    }
}

B - Equalize Prices

题意

有一大小为 $n$ 的数组 $a$,每个元素变化的绝对值不超过 $k$,该数组的所有元素能否变为同一个值。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n, k; cin >> n >> k;
    int mi = 1e9, mx = 0;
    for (int i = 0; i < n; i++) {
        int x; cin >> x;
        mi = min(mi, x);
        mx = max(mx, x);
    }
    if (mi + k >= mx - k) cout << mi + k << "\n";
    else cout << -1 << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

C - Computer Game

题意

电脑还有 $k$ 点电量,一个游戏有 $n$ 轮,每轮可进行如下选择:

  • 如果剩余电量大于 $a$,可以玩一轮,消耗 $a$ 点电量
  • 如果剩余电量大于 $b$,可以充电玩一轮,消耗 $b$ 点电量
  • 如果剩余电量小于等于 $a$ 或 $b$,终止游戏

判断是否可以玩完 $n$ 轮游戏,如果可以,最多能不充电玩几轮。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int k, n, a, b; cin >> k >> n >> a >> b;
    --k;
    if (k / b >= n) {
        int ex = k - min(n, k / b) * b;
        cout << min(n, ex / (a - b)) << "\n";
    } else 
        cout << -1 << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

D - Candy Box (easy version)

题意

给出 $n$ 个礼物的种类,选择一些种类的礼物,要求不同种类的礼物数量不同,问所选礼物的数量最多为多少。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n; cin >> n;
    int cnt[n] = {};
    for (int i = 0; i < n; i++) {
        int a; cin >> a;
        --a;
        cnt[a]++;
    }
    sort(cnt, cnt + n, greater<int>());
    int ans = 0;
    int p = 0;
    for (int i = n; i > 0; i--) {
        if (cnt[p] >= i) {
            ans += i;
            ++p;
        }
    }
    cout << ans << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

E - Subsequences (easy version)

见 H 。

F - Topforces Strikes Back

题意

从 $n$ 个数中最多选 $3$ 个数,要求所选数两两不整除(即互质),问所选数之和的最大值。

题解

怎么说呢...有些玄学...

大致来讲就是贪心地选择可以选择的最大的数,然后特判一下 $2,3,5$ 的情况,因为 $\frac{1}{2} + \frac{1}{3} + \frac{1}{5} > 1$ 。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n; cin >> n;
    set<int> st;
    for (int i = 0; i < n; i++) {
        int x; cin >> x;
        st.insert(x);
    }
    int ans = 0;
    int mx = *st.rbegin();
    if (mx % 2 == 0 and mx % 3 == 0 and mx % 5 == 0) {
        if (st.count(mx / 2) and st.count(mx / 3) and st.count(mx / 5)) {
            ans = max(ans, mx / 2 + mx / 3 + mx /5);
        }
    }
    vector<int> res;
    while (!st.empty() and res.size() < 3) {
        int x = *st.rbegin();
        st.erase(prev(st.end()));
        bool ok = true;
        for (auto it : res) ok &= (it % x != 0);
        if (ok) res.push_back(x);
    }
    ans = max(ans, accumulate(res.begin(), res.end(), 0));
    cout << ans << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

G - Candy Box (hard version)

题意

给出 $n$ 个礼物的种类和是否想保留,选择一些种类的礼物,要求不同种类的礼物数量不同,问所选礼物的数量、保留礼物的数量最多分别为多少。

代码(priority_queue)

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n; cin >> n;
    int cnt[n] = {};
    int cnt_good[n] = {};
    for (int i = 0; i < n; i++) {
        int a, f; cin >> a >> f;
        --a;
        cnt[a]++;
        if (f) cnt_good[a]++;
    }
    vector<int> types[n + 1];
    for (int i = 0; i < n; i++) {
        types[cnt[i]].push_back(cnt_good[i]);
    }
    int ans1 = 0, ans2 = 0;
    priority_queue<int> cur;
    for (int i = n; i > 0; i--) {
        for (auto j : types[i]) cur.push(j);
        if (!cur.empty()) {
            ans1 += i;
            ans2 += min(i, cur.top());
            cur.pop();
        }
    }
    cout << ans1 << ' ' << ans2 << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

代码(multiset)

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n; cin >> n;
    int cnt[n] = {};
    int cnt_good[n] = {};
    for (int i = 0; i < n; i++) {
        int a, f; cin >> a >> f;
        --a;
        cnt[a]++;
        if (f) cnt_good[a]++;
    }
    vector<int> types[n + 1];
    for (int i = 0; i < n; i++) {
        types[cnt[i]].push_back(cnt_good[i]);
    }
    int ans1 = 0, ans2 = 0;
    multiset<int> cur;
    for (int i = n; i > 0; i--) {
        for (auto j : types[i]) cur.insert(j);
        if (!cur.empty()) {
            int mx = *cur.rbegin();
            ans1 += i;
            ans2 += min(i, mx);
            cur.erase(cur.find(mx));
        }
    }
    cout << ans1 << ' ' << ans2 << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

H - Subsequences (hard version)

题意

给出一个字符串 $s$,选取一个子序列的花费为选取该序列所需去掉的字符个数,问选取 $k$ 个不同子序列的最少花费为多少。

代码

#include <bits/stdc++.h>
using ll = long long;
using namespace std;
const ll INF = 1e12;

int main() {
    ll n, k; cin >> n >> k;
    --k; //原字符串算一个序列,不需要去掉任何字符
    string s; cin >> s;

    int lst[n][26] = {};
    fill(*lst, *lst + n * 26, -1);    
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 26; j++) {
            if (i > 0) lst[i][j] = lst[i - 1][j]; 
        }
        lst[i][s[i] - 'a'] = i;
    }

    ll dp[n + 1][n + 1] = {};
    for (int i = 0; i < n; i++) dp[i][1] = 1;

    for (int len = 2; len < n; len++) {
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < 26; j++) {
                if (lst[i - 1][j] != -1) {
                    dp[i][len] = min(INF, dp[i][len] + dp[lst[i - 1][j]][len - 1]);
                }
            }
        }
    }

    ll ans = 0;
    for (int len = n - 1; len >= 1; len--) {
        ll cnt = 0;
        for (int j = 0; j < 26; j++) {
            if (lst[n - 1][j] != -1) {
                cnt += dp[lst[n - 1][j]][len];
            }
        }
        if (cnt >= k) {
            ans += k * (n - len);
            k = 0;
            break;
        } else {
            ans += cnt * (n - len);
            k -= cnt;
        }
    }

    if (k == 1) {
        ans += n;
        --k;
    }

    if (k > 0) cout << -1 << "\n";
    else cout << ans << "\n";
}

 

posted @ 2020-05-14 20:34  Kanoon  阅读(181)  评论(0)    收藏  举报