题解:P11472 命运黄之瓜
出题人来啦~
~大家要好好品鉴题目背景哦~
以下是正文:
不妨假设
令
从高向低枚举答案的第
-
由于
a 小于b ,所以可以确定a 的i 至30 位的值,使用线性基C 的i+31 至61 位构造a 。 -
将
C 的0 至i+30 位取出,将这i+31 个数分别并上(2^{31}-1) 后,再做一次线性基得到线性基D 。 -
不难发现可以使用
D 确定b 的最大值b_{\max} ,若\frac{b_{\max}}{2^{i}}<\frac{a}{2^{i}} 则与a 不大于b 矛盾。
不难发现若第一步构造成功并且第三步没有矛盾则表明答案的第
枚举结束即可得到
单次询问时间复杂度
std:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define ll long long
const int MAXN=2e5+5;
int a[MAXN],b[MAXN],n;
void add(ll *a,ll x) {
for(int j=61; j>=0; j--)if(x>>j&1) {
if(!a[j]) {
a[j]=x;
return;
} else x^=a[j];
}
}
int work(int* a,int* b) {
ll c[62]= {0},d[62]= {0};
for(int i=1; i<=n; i++)add(c,(ll)a[i]<<31|b[i]);
int A=0,B=0;
for(int i=30; i>=0; i--)if(c[i+31]) {
if(~A>>i&1) {
A^=c[i+31]>>31;
B^=c[i+31]&0x7fffffff;
}
memcpy(d,c,sizeof(ll)*31);
for(int j=31; j<i+31; j++)add(d,c[j]&0x7fffffff);
int nb=B;
for(int j=30; j>=0; j--)nb=max((ll)nb,nb^d[j]);
if((nb>>i)<(A>>i)) {
A^=c[i+31]>>31;
B^=c[i+31]&0x7fffffff;
}
}
for(int j=30; j>=0; j--)B=max((ll)B,B^c[j]);
return min(A,B);
}
int main() {
int t;
cin>>t;
while(t--) {
scanf("%d",&n);
for(int i=1; i<=n; i++)scanf("%d",a+i);
for(int i=1; i<=n; i++)scanf("%d",b+i);
printf("%d\n",max(work(a,b),work(b,a)));
}
return 0;
}