【GDOI2022PJD1T2 數列遊戲】題解
阿新 • • 發佈:2022-04-22
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的情況,就是存在字首異或和相等。
以後對於區間異或的情況可以多往這個方面想。