Codeforces Round #732 (Div. 2)【ABCD】

Kanoon發表於2021-07-13

比賽連結:https://codeforces.com/contest/1546

A. AquaMoon and Two Arrays

題意

給出兩個大小為 \(n\) 的陣列 \(a, b\) ,每次可以選擇 \(a\) 中的兩個元素分別加一減一,計算將 \(a\) 變為 \(b\) 的操作次數和步驟。

題解

資料範圍較小,直接模擬即可。

若資料範圍較大,可用棧或佇列分別儲存 \(a_i \lt b_i\)\(a_i \gt b_i\) 的數,這樣每次查詢的時間複雜度就降到了 \(O_{(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 n;
        cin >> n;
        vector<int> a(n), b(n);
        int suma = 0, sumb = 0;
        for (int i = 0; i < n; i++) {
            cin >> a[i];
            suma += a[i];
        }
        for (int i = 0; i < n; i++) {
            cin >> b[i];
            sumb += b[i];
        }
        if (suma != sumb) {
            cout << -1 << "\n";
            continue;
        }
        vector<pair<int, int>> op;
        for (int i = 0; i < n; i++) {
            while (a[i] < b[i]) {
                for (int j = i + 1; j < n; j++) {
                    if (a[j] > b[j]) {
                        --a[j], ++a[i];
                        op.emplace_back(j, i);
                        break;
                    }
                }   
            }
            while (a[i] > b[i]) {
                for (int j = i + 1; j < n; j++) {
                    if (a[j] < b[j]) {
                        --a[i], ++a[j];
                        op.emplace_back(i, j);
                        break;
                    }
                }   
            }
        }
        cout << op.size() << "\n";
        for (auto [x, y] : op) {
            cout << x + 1 << ' ' << y + 1 << "\n";
        }
    }
    return 0;
}

B. AquaMoon and Stolen String

題意

\(n\) 個字串,將 \(n - 1\) 個字串中同一位上的字元相互交換,給出原來的 \(n\) 個字串和操作後的 \(n - 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 n, m;
        cin >> n >> m;
        string ans(m, 0);
        for (int i = 0; i < 2 * n - 1; i++) {
            string s;
            cin >> s;
            for (int j = 0; j < m; j++) {
                ans[j] ^= s[j];
            }
        }
        cout << ans << "\n";
    }
    return 0;
}

C. AquaMoon and Strange Sort

題意

給出 \(n\) 個數,初始時均朝右(朝向不影響數值大小),每次操作可以選取相鄰的兩個數交換位置並反轉朝向,判斷能否將 \(n\) 個數排為升序後仍都朝右。

題解

若一個數操作後仍朝右,那麼它移動的距離一定是 2​ 的倍數,即位置的奇偶性不變,判斷排序前後同一值的奇偶位置個數是否相同即可。

程式碼

#include <bits/stdc++.h>
using namespace std;
constexpr int N = 1e5 + 10;
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];
        }
        vector<vector<int>> pos_before(N, vector<int> (2));
        for (int i = 0; i < n; i++) {
            ++pos_before[a[i]][i & 1];
        }
        sort(a.begin(), a.end());
        vector<vector<int>> pos_after(N, vector<int> (2));
        for (int i = 0; i < n; i++) {
            ++pos_after[a[i]][i & 1];
        }
        cout << (pos_before == pos_after ? "Yes" : "No") << "\n";
    }
    return 0;
}

D. AquaMoon and Chess

題意

給出一個 01 串,每個 1 只能隔著一個 1 與 0 交換位置,計算 01 串最終可能狀態的個數。

題解

將相鄰的兩個 1 看作一個整體,設 0 的個數為 \(n\) ,無交集的 11 個數為 \(m\) ,答案即 \(C_{n + m}^{m}\)

在奇數長度的連續 1 串中,有一個 1 因為無法移動,在所有可能狀態中的位置都是固定的。

程式碼

#include <bits/stdc++.h>
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;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    Init();
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        string s;
        cin >> s;
        int one = 0;
        for (int i = 0; i + 1 < n; i++) {
            if (s[i] == '1' and s[i + 1] == '1') {
                ++one, ++i;
            }
        }
        int zero = count(s.begin(), s.end(), '0');
        cout << C(one + zero, one) << "\n";
    }
    return 0;
}

參考

https://codeforces.com/blog/entry/92739

後記

蠻有思維難度的一場比賽,學到很多 ( ̄▽ ̄) /

相關文章