Educational Codeforces Round 134 (Rated for Div. 2)D. Maximum AND

78 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

传送门 image.png

题意

给你a和b序列,c序列由aibia_i⊕b_i得到,现在问你在能对b序列以任意方式排列的情况下,c序列按位并的和是多少

思路

首先能确定的是:我们需要尽量使高位1能在按位并时保留下来,因而就形成了一个大致的解题思路:从30位到0位,判断能否保留每一位。 为了使选取的某一位保留,需要使a和b中的每一对数字aibi2i=1a_i⊕b_i是∧2^i=1,这里为了方便处理,于是将b按位取反,于是变成了aibi2i=2ia_i∧b_i是∧2^i=2^i,但这是脱离其它位单独看某一位的情况,因而我们可以设置一个ans,当某一位能被保留下来时,就将该位加入ans中,同时,在判断第i位能否被保留时,只需要判断ans|2i2^i能否被保留。

using namespace std;
#define endl '\n'
typedef long long ll;

int read()
{
	int num=0;
	char c=getchar();
	while(c<'0' || c>'9') c=getchar();
	while(c>='0' && c <='9')
	{
		num=num*10+c-'0';
		c=getchar();
	}
	return num;
}



int a[100005],b[100005];

void solve()
{
	int n;
	cin>>n;
	for(int i = 1; i <= n; i++){
		cin>>a[i];
	}
	for(int i = 1; i <= n; i++){
		cin>>b[i];
		b[i] = ~b[i];
	}
	int ans = 0;
	for(int i = 30; i >= 0; i--){
		if(i == 4){
			cout<<"\n";
		}
		int sum = 0,cnta = 0,cntb = 0;
		vector<int>aa,bb;
		for(int j = 1; j <= n; j++){
			aa.push_back(a[j]&(ans|1<<i));
			bb.push_back(b[j]&(ans|1<<i));
		}
		sort(aa.begin(),aa.end());
		sort(bb.begin(),bb.end());
		for(int j = 0; j < n; j++){
			if(aa[j] != bb[j])break;
			if(j == n-1)ans|=1<<i;
		}
	}
	cout<<ans<<endl;
} 

int main()
{
	int t;
	t=read();
	while(t--)
	{
		solve();
	}
}```