1. 程式人生 > 實用技巧 >webpack:hash、chunkhash、contenthash三者區別

webpack:hash、chunkhash、contenthash三者區別

CF1438D Powerful Ksenia

題目來源:Codeforces, Codeforces Round #682 (Div. 2),CF1438D Powerful Ksenia

題目大意

題目連結

給出 \(n\) 個正整數 \(a_1,a_2,\dots,a_n\)

在一次操作中,你可以:

  • 選擇三個不同的下標 \(i\), \(j\), \(k\)
  • \(a_i\), \(a_j\), \(a_k\) 三個值,全部置為 \((a_i\operatorname{xor} a_j\operatorname{xor} a_k)\)

請通過不超過 \(n\) 次操作,使得序列裡所有數都相等。注意:不需要最小化運算元量。

資料範圍:\(1\leq n\leq 10^5\)\(1\leq a_i\leq 10^9\)

本題題解

首先,當 \(n\) 為奇數時,不論 \(a\) 中的數是什麼,我們一定可以構造出一組解。具體方法如下:

考慮,如果序列裡,除某個數 \(a_p\) 外,其他(剩下偶數個數)數能兩兩配對,使得每對數相等。設配出的 \(\frac{n-1}{2}\) 對下標分別為 \((u_1,v_1),(u_2,v_2),\dots,(u_{\frac{n-1}{2}},v_{\frac{n-1}{2}})\)。則我們接下來只需要依次操作:

  • \((p,u_1,v_1)\)
  • \((p,u_2,v_2)\)
  • \(\dots\)
  • \((p,u_{\frac{n-1}{2}},v_{\frac{n-1}{2}})\)

就能使得序列裡所有數都等於 \(a_p\)。這是因為 \(a_{u_i}=a_{v_i}\),所以每次三個數異或起來時,\(a_{u_i},a_{v_i}\) 就會自己抵消掉,剩下 \(a_p\)。即:\(\forall i:(a_{u_i}\operatorname{xor}a_{v_i}\operatorname{xor}a_p)=a_p\)。這部分一共需要 \(\frac{n-1}{2}\) 次操作。

思考如何達到這種 \(\frac{n-1}{2}\) 對數兩兩相等的局面。可以依次對所有 \(i=1,3,5,\dots ,n-2\)

,做操作 \((i,i+1,i+2)\)。這樣,就能使所有 \((i,i+1)\) 相等(\(i=1,3,5,\dots,n-2\))。最後剩下 \(p=n\)。然後進行上述操作即可。

總共需要 \(\frac{n-1}{2}+\frac{n-1}{2} = n-1\) 次操作。


\(n\) 是偶數時,首先要觀察到,一次操作不會改變序列裡所有數的異或和。而最終序列中要求所有數都相等,異或和一定是 \(0\),所以原序列的異或和也一定要是 \(0\)

那麼首先判斷,如果原序列異或和不為 \(0\),則直接輸出 \(\text{NO}\)

否則我們隨便拿出一個數,不妨拿出 \(a_n\)。剩下奇數個數 \(a_1,a_2,\dots,a_{n-1}\),通過上述的構造,一定能變成所有數都相等的情況,設這個相等的值為 \(x\)。那麼這 \(n-1\) 個數的異或和也為 \(x\)。因為序列裡所有數異或和為 \(0\),所以一定有 \(x=a_n\)。於是我們根本不需要考慮 \(a_n\),直接對前 \(n-1\) 個數用奇數的方法構造即可。


時間複雜度 \(O(n)\)

總結

\(n\) 是奇數的情況,是比較簡單的構造。自己手玩一會應該就能看出來。

\(n\) 是偶數時,用到一個技巧:觀察每次操作不變的量(例如本題中是異或和。其他題目有時是奇偶性等等)。那麼,開始局面的這個量,必須和目標局面相等。也就是說,我們找到一個必要條件。然後思考這個必要條件是否充分。如果充分,我們也就構造出了操作的方法。

參考程式碼

// problem: CF1438D
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define mk make_pair
#define lob lower_bound
#define upb upper_bound
#define fi first
#define se second
#define SZ(x) ((int)(x).size())

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

template<typename T> inline void ckmax(T& x, T y) { x = (y > x ? y : x); }
template<typename T> inline void ckmin(T& x, T y) { x = (y < x ? y : x); }

const int MAXN = 1e5;
int n, a[MAXN + 5];
struct Oper_t {
	int i, j, k;
	Oper_t() {}
	Oper_t(int _i, int _j, int _k) { i = _i, j = _j, k = _k; }
};
void solve_odd() {
	cout << "YES" << endl;
	vector<Oper_t> ans;
	for (int i = 1; i <= n - 2; i += 2) {
		ans.pb(Oper_t(i, i + 1, i + 2));
	}
	for (int i = 1; i <= n - 2; i += 2) {
		ans.pb(Oper_t(i, i + 1, n));
	}
	cout << SZ(ans) << endl;
	for (int i = 0; i < SZ(ans); ++i) {
		cout << ans[i].i << " " << ans[i].j << " " << ans[i].k << endl;
	}
}
void solve_even() {
	int xorsum = 0;
	for (int i = 1; i <= n; ++i) xorsum ^= a[i];
	if (xorsum) {
		cout << "NO" << endl;
		return;
	}
	--n;
	solve_odd();
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; ++i) cin >> a[i];
	if (n % 2 == 0) {
		solve_even();
	} else {
		solve_odd();
	}
	return 0;
}