Codeforces Round #725 (Div. 3)

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

A. Stone Game

题解

从一侧取:两种情况

从两侧取:一种情况

取三种情况的最小值。

代码

#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> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        int p1 = min_element(a.begin(), a.end()) - a.begin();
        int p2 = max_element(a.begin(), a.end()) - a.begin();
        cout << min({max(p1, p2) + 1,  n - min(p1, p2), (min(p1, p2) + 1) + (n - max(p1, p2))}) << "\n";
    }
    return 0;
}

B. Friends and Candies

题解

如果总和不能平分则无解,否则将多于平均的数重新分配。

代码

#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> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        sort(a.begin(), a.end());
        int sum = accumulate(a.begin(), a.end(), 0);
        if (sum % n != 0) {
            cout << -1 << "\n";
        } else {
            cout << n - (upper_bound(a.begin(), a.end(), sum / n) - a.begin()) << "\n";
        }
    }
    return 0;
}

C. Number of Pairs

题解

二分所能加的数的左右边界。

代码

#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, l, r;
        cin >> n >> l >> r;
        vector<int> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        sort(a.begin(), a.end());
        long long ans = 0;
        for (int i = 0; i < n; i++) {
            auto it1 = lower_bound(a.begin() + i + 1, a.end(), l - a[i]);
            auto it2 = upper_bound(a.begin() + i + 1, a.end(), r - a[i]);
            ans += it2 - it1;           
        }
        cout << ans << "\n";
    }
    return 0;
}

D. Another Problem About Dividing Numbers

题解

最少操作次数:将 \(a,b\)\(gcd(a, b)\) 转化,

  • \(gcd(a, b) = a\)\(gcd(a, b) = b\) 时,最少操作 \(0\)
  • \(gcd(a, b) = a\)\(gcd(a, b) = b\) 时,最少操作 \(1\)
  • \(gcd(a, b) \ne a\)\(gcd(a, b) \ne b\) 时,最少操作 \(2\)

最多操作次数:将 \(a, b\)\(1\) 转化,为两者所有质因子的幂次之和。

如果 \(k\) 位于两者之间则有解。

因为最少操作次数为 \(2\) 次,所以特判 \(k = 1\) 的情况,然后判断 \(k\) 是否小于最多操作次数即可。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    constexpr int N = 1e5;
    vector<int> isPrime(N, true);
    for (int i = 2; i < N; i++) {
        for (int j = i + i; j < N; j += i) {
            isPrime[j] = false;
        }
    }
    vector<int> Primes;
    for (int i = 2; i < N; i++) {
        if (isPrime[i]) {
            Primes.push_back(i);
        }
    }
    int t;
    cin >> t;
    while (t--) {
        int a, b, k;
        cin >> a >> b >> k;
        if (k == 1) {
            if (a == b) {
                cout << "NO" << "\n";
            } else if (a % b == 0 or b % a == 0) {
                cout << "YES" << "\n";
            } else {
                cout << "NO" << "\n";
            }
            continue;
        }
        auto Count_Expo = [&](int n) {
            int res = 0;
            for (auto i : Primes) {
                while (n % i == 0) {
                    ++res;
                    n /= i;
                }
            }
            if (n != 1) {
                ++res;
            }
            return res;
        };
        cout << (k <= Count_Expo(a) + Count_Expo(b) ? "YES" : "NO") << "\n";
    }
    return 0;
}

E. Funny Substrings

题解

因为 \(haha\) 长为 \(4\) ,所以保存一个字符串首尾的 \(3\) 个字符及 \(haha\) 的个数。

代码

#include <bits/stdc++.h>
using namespace std;
struct P{
    string front;
    string back;
    long long cnt_haha = 0;
};
P cal(const string& s) {
    P res;
    res.front = s.substr(0, 3);
    res.back = s.substr(max(0, (int)s.size() - 3));
    for (int i = 0; i < (int)s.size(); i++) {
        if (s.substr(i, 4) == "haha") {
            ++res.cnt_haha;
        }
    }
    return res;
}
P merge(const P& a, const P& b) {
    P res;
    res.front = (a.front + b.front).substr(0, 3);
    res.back = (a.back + b.back).substr(max(0, (int)a.back.size() + (int)b.back.size() - 3));
    res.cnt_haha = a.cnt_haha + b.cnt_haha + cal(a.back + b.front).cnt_haha;
    return res;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        map<string, P> mp;
        for (int i = 0; i < n; i++) {
            string name, op;
            cin >> name >> op;
            if (op == ":=") {
                string str;
                cin >> str;
                mp[name] = cal(str);
            } else if (op == "=") {
                string a, b;
                char ch;
                cin >> a >> ch >> b;
                mp[name] = merge(mp[a], mp[b]); 
            }
            if (i == n - 1) {
                cout << mp[name].cnt_haha << "\n";
            }
        }
    }
    return 0;
}

F. Interesting Function

题解

依次计算每一位对前一位产生了多少进位。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        int l, r;
        cin >> l >> r;
        string s1 = to_string(l), s2 = to_string(r);
        s1 = string(s2.size() - s1.size(), '0') + s1;
        int ans = 0, carry = r - l;
        for (int i = s1.size() - 1; i >= 0; i--) {
            ans += carry;
            carry = (carry + s1[i] - '0') / 10;
        }
        cout << ans << "\n";
    }
    return 0;
}

G. Gift Set

题解

因为总次数具有单调性,所以考虑对其二分。

若某次所二分的总次数值为 \(n\) ,假设进行了操作一 \(k\) 次,那么有:

  • \(a \times k + b \times (n - k) \le x\)
  • \(b \times k + a \times (n - k) \le y\)

不妨令 \(a \gt b\) , 化简得:

  • \(k \le \frac{x - b \times n}{a - b}\)
  • \(k \ge \frac{y - a \times n}{b - a} = \frac{a \times n - y}{a - b}\)

同时,有:

  • \(k \ge 0\)
  • \(k \le n\)

若上述四个不等式在数轴上有交集,则 \(k\) 存在,表示当前二分值 \(n\) 可行。

Tips

若分子 \(a\) 可能为正负整数,分母 \(b\) 为正整数,则有:

  • 取上整: \(\lfloor \frac{a + b - 1}{b} \rfloor\)
  • 取下整: \(\lfloor \frac{a + b}{b} \rfloor - 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 x, y, a, b;
        cin >> x >> y >> a >> b;
        if (a == b) {
            cout << min(x, y) / a << "\n";
            continue;
        }
        if (a < b) {
            swap(a, b);
        }
        int l = 0, r = (x + y) / (a + b);
        while (l < r) {
            int n = (l + r + 1) / 2;
            int L = max(0, (a * n - y + a - b - 1) / (a - b));
            int R = min(n, (x - b * n + a - b) / (a - b) - 1);
            if (L <= R) {
                l = n;
            } else {
                r = n - 1;
            }
        }
        cout << l << "\n";
    }
    return 0;
}
posted @ 2021-06-12 22:00  Kanoon  阅读(181)  评论(4编辑  收藏  举报