Codeforces Round #697 (Div. 3) A -D 解题报告

A. Odd Divisor

题意:

判断一个数是否存在 (>1) 的奇因数。

思路:

将一个数分解质因数显然可以发现除 (2) 都是奇数,那么我们只需要判断该数是不是 (2) 的整数次幂即可。

代码:
int main() {

    int t; cin >> t;
    while (t --) {
        ll n; cin >> n;
        while (n % 2 == 0) n >>= 1;
        if (n == 1) puts("NO");
        else puts("YES");
    }
    return 0;
}

B. New Year's Number

题意:

给定一个数 (n),问你能否构造如下等式:(n = 2020 imes x + 2021 imes y)。( (x, y) 均为大于等于零的整数)

思路:

将上述等式变换:(n = 2020 imes(x+y) + y)

那么显然 (x + y = frac{n}{2020})(y = n \% 2020)

显然 (y > x + y) 时等式不成立。

代码:
int main() {

    int t; cin >> t;
    while (t --) {
        int n; cin >> n;
        int x = n / 2020;
        int y = n % 2020;
        if (y > x) puts("NO");
        else puts("YES");
    }
    return 0;
}

C. Ball in Berland

题意:

给定男女的匹配关系,从中选出两对男女(没有重复的人),问有几种选法?

思路:

由于固定了只选择两对,那么我们可以枚举其中的一对关系 (a),而另一对中的人一定是 (a) 中没有出现过的,可以利用容斥原理,用 (k) - (a) 中出现过的人的关系数 + 1 即另一对可以选择的数量。(+1是因为会重复减一次)。

代码:
map<int, int> man, woman;

vector<int> v_man, v_woman;

int main() {

    int t; cin >> t;
    while (t --) {
        man.clear();
        woman.clear();
        v_man.clear();
        v_woman.clear();
        int a, b, k;
        cin >> a >> b >> k;
        for (int i = 1; i <= k; i ++) {
            int x; cin >> x;
            v_man.pb(x);
            man[x] ++;
        }
        for (int i = 1; i <= k; i ++) {
            int x; cin >> x;
            v_woman.pb(x);
            woman[x] ++;
        }
        ll ans = 0;
        for (int i = 0; i < k; i ++) {
            int tmp_man = v_man[i];
            int tmp_woman = v_woman[i];
            ans += k - man[tmp_man] - woman[tmp_woman] + 1;
        }
        cout << ans / 2 << endl;
    }
    return 0;
}

D. Cleaning the Phone

题意:

(n) 个应用程序,第 (i) 个占用的内存为 (a_i),删除它的花费为 (b_i)。要求你至少腾出 (m) 的内存,问最少花费是多少?如果删光了所有应用都不行,就输出 -1

思路:

由于 (b_i) 的取值只有 (1)(2)。那么我们就可以根据这个来分组,然后按内存从大到小排序,求一个前缀和,然后枚举某一组,用二分算出另一组。注意只选取某一组的特殊情况。

代码:
bool cmp(ll a, ll b) { return a > b; }

int main() {

    int t; cin >> t;
    while (t --) {
        int n, m;
        vector<ll> memory, v1, v2, sum1, sum2;
        cin >> n >> m;
        ll sum = 0;
        for (int i = 1; i <= n; i ++) {
            int x; cin >> x;
            sum += x;
            memory.pb(x);
        }
        for (int i = 1; i <= n; i ++) {
            int x; cin >> x;
            if (x == 1) {
                v1.pb(memory[i - 1]);
            } else {
                v2.pb(memory[i - 1]);
            }
        }        
        if (sum < m) {
            puts("-1");
            continue;
        }
        sort(all(v1), cmp);
        sort(all(v2), cmp);
        int len_v1 = v1.size();
        int len_v2 = v2.size();
        ll pre = 0;
        for (int i = 0; i < len_v1; i ++) {
            sum1.pb(pre + v1[i]);
            pre = sum1[i];
        }
        pre = 0;
        for (int i = 0; i < len_v2; i ++) {
            sum2.pb(pre + v2[i]);
            pre = sum2[i];
        }
        int ans = INF;
        int len_sum1 = sum1.size();
        int len_sum2 = sum2.size();
        // 全部选 2 的
        int idx = lower_bound(all(sum2), m) - sum2.begin();
        if (idx < len_sum2) ans = min(ans, (idx + 1) * 2);
        for (int i = 0; i < len_sum1; i ++) {
            ll tmp1 = sum1[i];
            ll tmp2 = m - tmp1;
            if (tmp2 <= 0) {
                ans = min(ans, i + 1);
                break;
            } else {
                int idx = lower_bound(all(sum2), tmp2) - sum2.begin();
                if (idx < len_sum2) ans = min(ans, i + 1 + (idx + 1) * 2);
            }
        }
        cout << ans << endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/nonameless/p/14343504.html