题目
t(t<=1e5)组样例,每次给定l,r(0<=l<r<2^17)
和r-l+1个数ai,新序列是被[l,r]这些数异或上同一个x得到的,
求出x,有多个输出任意一个即可
思路来源
官方题解
洛谷题解
Educational Codeforces Round 157 (Rated for Div. 2) D. XOR Construction (思维题)-CSDN博客
心得
Educational Codeforces Round 157 (Rated for Div. 2) 是该题的减弱版,感觉一模一样
题解1(性质)
注意到,若a^b=1,则(a^x)^(b^x)=1恒成立
如果l是偶数,r是奇数,那么x的末尾是0或1均可,因为总可以将ai和ai^1两两配对
此时可以将末位除掉,规模递减到原来一半,继续递归
否则,当我们将ai和ai^1两两配对时,
由于原序列末位所构成序列,形如01010或者10101,必有一个无法配对
l%2==0时,r无法配对,否则l无法配对,记原来无法配对的数为ans
遍历这r-l+1个数,找到无法配对的那一个ai,ans^ai=x成立,输出x即可
题解2(trie树)
r-l+1个数中,肯定有一个ai是l^x得到的,那么令每个数再异或l,
即令bi=ai^l,必有一个bi是等于x的,
将每个ai插入到trie上,枚举bi,
若存在一个bi,min(bi^trie)=l,max(bi^trie)=r,则bi即为x所求
其中,min(bi^trie)表示取trie上一个数和bi异或能得到的最小值,
max表示取trie上一个数和bi异或能得到的最大值
代码1(性质)
#include <bits/stdc++.h>
using namespace std;const int N = 2e5 + 5;
int a[N], l, r;
set <int> s, s2;void solve() {int mul = 1;s.clear();cin >> l >> r; for (int i = l; i <= r; ++i) {cin >> a[i];s.insert(a[i]);}for (; l % 2 == 0 && r % 2 == 1; l >>= 1, r >>= 1, mul <<= 1) {s2.clear();for (int i: s) s2.insert(i >> 1);swap(s, s2); }int ans;if (l % 2 == 0) ans = r;else ans = l;for (int i: s) {if (s.find(i ^ 1) == s.end()) {int cur = i ^ ans;bool f = true;for (int j : s)f &= ((cur ^ j) >= l && (cur ^ j) <= r);if (f) {ans = cur;break;}}}cout << ans * mul << '\n';
}int main() {ios_base::sync_with_stdio(false);cin.tie(NULL);int t; cin >> t;while (t--) solve();return 0;
}
代码2(trie树)
#include<bits/stdc++.h>
#define N 1000005
#define int long long
using namespace std;
int T,l,r,a[N],cnt,trie[N][30],b[N];
void insert(int sum){int now=0;for(int i=17;i>=0;i--){bool tmp=(1<<i)∑if(!trie[now][tmp])trie[now][tmp]=++cnt;now=trie[now][tmp];}
}
int Max(int sum){int now=0,res=0;for(int i=17;i>=0;i--){bool tmp=(1<<i)∑if(!trie[now][tmp^1])now=trie[now][tmp];else now=trie[now][tmp^1],res+=(1<<i);}return res;
}
int Min(int sum){int now=0,res=0;for(int i=17;i>=0;i--){bool tmp=(1<<i)∑if(!trie[now][tmp])now=trie[now][tmp^1],res+=(1<<i);else now=trie[now][tmp];}return res;
}
signed main() {cin>>T;while(T--){cin>>l>>r;for(int i=0;i<=cnt;i++)trie[i][0]=trie[i][1]=0;cnt=0;for(int i=l;i<=r;i++)cin>>a[i],b[i]=a[i]^l;for(int i=l;i<=r;i++)insert(a[i]);for(int i=l;i<=r;i++){if(Max(b[i])==r&&Min(b[i])==l){cout<<b[i]<<endl;break;}}}
}