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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM