Codeforces Round #717 (Div. 2) 个人题解 A~C (A思維,B位運算,C背包DP)

1516A. Tit for Tat

題意:

給定大小為 \(n\) 的數組和可操作次數 \(k\)

  • 每次操作都選定兩個數(如果 \(1 \le a_i\) ),使第一個數 - \(1\) ,另一個數 + \(1\)

輸出字典序最小的數組

思路:

既然要輸出字典序最小,那麽肯定是選最前面 - 1,最後 + 1

void solve() {
    int n, k;
    cin >> n >> k;
    int a[n + 1];
    for (int i = 1; i <= n; ++i) cin >> a[i];
    int i = 1, j = n;
    while (true) {
        if (i == j || k == 0) break;
        if (a[i] >= 1) a[i] -= 1, a[j] += 1, k--;
        else
            i++;
    }
    for (int i = 1; i <= n; ++i) cout << a[i] << " ";
    cout << "\n";
}

1516B. AGAGA XOOORRR

題意:

思路:

我采取的方法是模擬,首先求出全部元素的 XOR 結果,如果 \(s = 0\) 則是元素兩兩相等的情況比如:\(0,2,2,1,1,3,3...\) 此時輸出 YES 即可。

維護 \(t\) 如果 \(t == s\) 則説明前面已使用的一段可以 XOR 為同一個值,此時 \(t = 0,cnt += 1\)

如果最後 cnt > 2 && t == 0 則説明數組完全可以通過 XOR 操作簡化為相同的值

void solve() {
    int n;
    cin >> n;
    vector<int> a(n);
    for (int &x : a) cin >> x;
    int s = 0;
    for (int x : a) s ^= x;
    if (s == 0) {
        cout << "YES\n";
        return;
    }
    int t = 0, cnt = 0;
    for (int i = 0; i < n; ++i) {
        t ^= a[i];
        if (t == s) cnt++, t = 0;
    }
    if (cnt > 2 && t == 0) cout << "YES\n";
    else
        cout << "NO\n";
}

下面代碼為官方 AC 代碼:

void solve() {
    int n;
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1, x; i <= n; ++i) {
        cin >> x;
        a[i] = a[i - 1] ^ x;
    }
    bool f = !a[n];
    for (int i = 1; i <= n; ++i)
        for (int j = i + 1; j <= n; ++j)
            f |= (a[i] == (a[j] ^ a[i]) && a[i] == (a[n] ^ a[j]));
    cout << (f ? "YES\n" : "NO\n");
}

1516C. Baby Ehab Partitions Again

題意:

將數組劃分為兩個子序列,如果存在兩個子序列之和相等則被稱爲 “好數組” 現在請問是否能刪除幾個元素使得數組不是 “好數組”

思路:

首先,让我们检查一下数组是否已经很好。 这可以通过背包dp完成。 如果是,则答案为0。否则,可以始终删除一个元素以使其良好,这是找到它的方法:由于可以对数组进行分区,因此其总和为偶数。 因此,如果我们删除一个奇数元素,它将是奇数,并且将无法对其进行分区。 如果没有奇数元素,那么所有元素都是偶数。 但是,您可以将所有元素除以2,而无需更改答案。 为什么? 因为将所有内容都除以2后在新数组中进行的分区就是在原始数组中进行的分区,反之亦然。 我们只是重新缩放了一切。 因此,当所有元素都是偶数时,您可以继续除以2,直到其中一个元素变为奇数。 删除它,您就完成了。 如果您想用一句话来解决,请删除可能的最小有效位最小的元素。
另外,出于类似的推理,您可以先将整个数组除以其gcd,然后删除任何奇数元素(因为gcd为1,该元素必须存在)

int dp[200010];
void solve() {
    int n;
    cin >> n;
    vector<int> a(n + 1);
    int d = 0;
    for (int i = 1; i <= n; ++i) cin >> a[i], d = __gcd(d, a[i]);
    for (int i = 1; i <= n; ++i) a[i] /= d;
    dp[0] = 1;
    int S = 0, id = 0;
    for (int i = 1; i <= n; ++i) {
        S += a[i];
        if (a[i] & 1) id = i;
        for (int j = S; j >= a[i]; j--) dp[j] |= dp[j - a[i]];
    }
    if (S & 1 || dp[S / 2] == 0) cout << "0";
    else
        cout << "1\n"
             << id;
}
posted @ 2021-04-22 19:22  RioTian  阅读(38)  评论(0编辑  收藏