Codeforces 1847 A-F

chenaknoip發表於2024-11-06

題面

A B C D E F
難度:紅 橙 黃 藍 紫 紫

題解

B

題目大意:找到一組分割方法,使得 \(\sum _{i=1} ^ k (\text{&} _{j=l_i} ^ {r_i} a_j)\) 取得最小值時使 \(k\) 最大,輸出 \(k\)。其中 \(\text{&}\) 表示按位與操作。

題目分析:

& 0 1
0 0 0
1 0 1

不難發現,因為 \(a \in \mathbb{N}\),所以 $$a, b \ge a \& b \tag{1}$$ $$a + b \ge a \& b \tag{2}$$且對於公式 (2),當且僅當 \(a=b=0\) 時取等。
因此考慮貪心。設 \(x = \text{&} _{i=1} ^ {n} a_i\)。對於 \(x > 0\) 的 情況,根據 (2),分成一組的和是最優的,因此 \(k = 1\);對於 \(x = 0\) 的情況,只要將原陣列分為幾段區間按位與都為 \(0\) 的區間即可。
程式碼略。

C

題目大意:對於陣列 \(a\),它的前 \(n\) 個數由題目給定,而 \(a_i(i > n) = \oplus _{j=k} ^ {i-1} a_j\),其中 \(k\) 不確定,\(1 \le k \le i - 1\),而 \(\oplus\) 表示按位異或。求 \(a\) 中元素的最大可能值。
這套題怎麼這麼多位運算?
題目分析:

\(\oplus\) 0 1
0 0 1
1 1 0

題目給定 \(a_i < 2^8 (1\le i\le n)\),所以由按位與的定義得到全體 \(a_i < 2^8\)
\(a_p = \oplus _{i=l} ^{p-1} a_i\),則 \(a_{p+1}=\oplus _{i=k} ^{p} a_i=(\oplus _{i=k} ^{p-1} a_i) \oplus a_p = (\oplus _{i=k} ^{p-1} a_i) \oplus (\oplus _{i=l} ^{p-1} a_i) = \oplus _{i=min(k, l)} ^{max(k, l)-1} a_i\)
於是問題轉化為求最大欄位異或。又因為異或運算滿足結合律,可以用字首異或加速。
問題再次轉化為:求字首異或陣列中,任意兩數異或的最大值。
由於 \(a_i < 2^8\),所以字首異或陣列中元素的值也在這個值域內。因此考慮用桶記錄字首陣列中的數,然後與字首陣列進行“配對”求異或值。時間複雜度 \(O(2^8 \times n)\),可以透過這道題。

#include <bits/stdc++.h>
using namespace std;
int t, n, a[100010];
bool x[100010];
int main() {
	scanf("%d", &t);
	while (t--) {
		memset(x, 0, sizeof(x));
		scanf("%d", &n);
		int ans = 0;
		for (int i = 1; i <= n; i++) {
			scanf("%d", &a[i]);
			a[i] ^= a[i - 1];
			x[a[i]] = 1;
			ans = max(ans, a[i]);
		}
		for (int i = 1; i <= n; i++) {
			for (int j = 0; j < 256; j++) {
				if (x[j]) {
					ans = max(ans, a[i] ^ j);
				}
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

D

從這裡開始難度陡增。
(未完)

相關文章