ABC249G Xor Cards

好菜啊,ABC 都不会做。

考虑二进制的大小,我们可以利用钦定前若干位相同,下一位不同的方式来决定大小。考虑此时的小于等于 \(k\) ,实际上可以看成前若干位异或和等于一个钦定值的限制。然后对于另一个维度,我们则也是可以利用试错法来找到最大情况,实际上也是可以看成只考虑前若干位异或和等于一个钦定值的情况。

于是我们就可以愉快地利用线性基解决这个问题啦。

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

const int N=1e3+5,M=30;

int n;
long long k,a[N],b[N];

struct Linear_Basis{
	int cnt=0;
	long long f[M*2];
	void clear(){
		cnt=0;
		for(int i=0;i<60;++i) f[i]=0;
	}
	void insert(long long x){
		for(int i=0;i<60;++i){
			if(!((x>>i)&1)) continue;
			if(f[i]) x^=f[i];else return f[i]=x,void();
		}
		cnt++;
	}
	bool check(long long x){
		if(x==0) return cnt;
		for(int i=0;i<60;++i) if((x>>i)&1) x^=f[i];
		return x==0;
	}
}lb;

long long res=-1;

int main(){
	// freopen("1.in","r",stdin);

	cin>>n>>k;
	for(int i=1;i<=n;++i) scanf("%lld%lld",&a[i],&b[i]);

	for(int i=29;i>=0;--i){
		if(!((k>>i)&1)) continue;
		long long tmp=(k^(1<<i)),TMP=0;
		tmp=(tmp>>i)<<i;
		for(int j=29;j>=0;--j){
			lb.clear();
			for(int c=1;c<=n;++c){
				long long A=((a[c]>>i)<<i);
				long long B=((b[c]>>j)<<j);
				lb.insert((A<<30)|B);
			}
			if(lb.check((tmp<<30)|(TMP^(1<<j)))) TMP^=(1<<j);
		}
		lb.clear();
		for(int c=1;c<=n;++c){
			long long A=((a[c]>>i)<<i);
			long long B=b[c];
			lb.insert((A<<30)|B);
		}
		if(lb.check((tmp<<30)|TMP)) res=max(res,TMP);
	}
	{
		long long tmp=k,TMP=0;
		for(int j=29;j>=0;--j){
			lb.clear();
			for(int c=1;c<=n;++c){
				long long A=(a[c]);
				long long B=((b[c]>>j)<<j);
				lb.insert((A<<30)|B);
			}
			if(lb.check((tmp<<30)|(TMP^(1<<j)))) TMP^=(1<<j);
		}
		lb.clear();
		for(int c=1;c<=n;++c){
			long long A=a[c];
			long long B=b[c];
			lb.insert((A<<30)|B);
		}
		if(lb.check((tmp<<30)|TMP)) res=max(res,TMP);
	}

	printf("%lld\n",res);

	return 0;
}
posted @ 2022-04-24 16:42  Point_King  阅读(134)  评论(0编辑  收藏  举报