1. 程式人生 > 其它 >【GDOI2022PJD1T2 數列遊戲】題解

【GDOI2022PJD1T2 數列遊戲】題解

D1T2 數列遊戲

題目

有一個長度為 \(n\) 的序列 \(a_1, \dots , a_n\)

如果序列的長度大於 1,那麼你就能進行操作,每次操作可以選擇兩個相鄰的數 \(a_i, ai+1\) 合併,得到一個新的數 \(a_i\)\(a_{i+1}\)(“⊕”表示異或),每次操作都會使序列的長度減少 1。例如對將序列 \([8, 3, 5, 7, 1]\) 中的第 2個和第 3 個數進行合併,會得到新序列 \([8, 6, 7, 1]\),並可以進行下一輪操作。

你需要進行若干次操作(可能是 0 次),使得最終序列任意子區間的異或和不為 0。子區間的定義為連續的一段數 $ [a_l, a_{l+1}, \dots ,a_r](l \leqslant r)$。

求滿足條件的最終序列的最長長度。

思路

記數列 \(a\) 的異或字首和為 \(s\),則區間 \([l, r]\) 的異或和為 \(s_r\)\(s_{l-1}\)

我們要使任意區間異或和不為0,就是要是 \(s\) 互不相同且皆大於0.

因此,我們要將不符合要求的 \(s\) 消除。

假如我們想要讓某個 \(s_i\) 消除,我們只需要合併 \(i\)\(i+1\) 即可。

但在程式實現的過程中,我們並不需要模擬消除,只需要統計多少個不同的即可。

無解的情況是整個數列異或和為0。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'
){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x
<<3)+(ch^48);ch=getchar();}return x*f;}
//#define N
//#define M
//#define mo
int n, m, i, j, k, T;
map<int, int>mp; 

signed main()
{
//	freopen("tiaoshi.in", "r", stdin);
//	freopen("tiaoshi.out", "w", stdout);
	n=read(); mp[0]=1; 
	for(i=1; i<=n; ++i)
	{
		j=read(); k^=j; 
		if(!mp[k]) ++m, mp[k]=1; 
	}
	printf("%lld", (k==0 ? -1 : m)); 
	return 0;
}

總結

這道題在考場上沒想出來,值得反思。

對於區間異或和的問題,可以多思考字首異或和的思想。

而區間異或和為0的情況,就是存在字首異或和相等。

以後對於區間異或的情況可以多往這個方面想。