C. Jon Snow and his Favourite Number(构造)

确实非常巧妙

a i 1000 , k 1000 , a i k 1023 注意到a_i最大1000,k最大1000,所以a_i\oplus k最大是1023

k , j 所以直接暴力模拟k次,每次开个桶记录j这个数字出现了几次

i i + 1 ? 那么第i次操作的桶怎么转移到i+1次的桶呢?

j i w 假设当前j这个数字在第i次操作后出现了w次

, w j 那么根据只对奇数异或,因为w个j是连成一片的

w / 2 j , w / 2 j 所以有w/2个j去异或,有w/2个j保留

s j s w , w / 2 + 1 j 特判如果有s个数比j大且s是偶数w是奇数,那么有w/2+1个j去异或

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+20;
int n,k,x,a[maxn],f[maxn],t[maxn];
int main()
{
	cin >> n >> k >> x;
	for(int i=1;i<=n;i++)	cin >> a[i],f[ a[i] ]++;
	for(int i=1;i<=k;i++)
	{
		int s=0;//比j小的数量 
		for(int j=0;j<=1024;j++)	t[j]=f[j];
		for(int j=0;j<1024;j++)
		{
			if(f[j]==0)	continue;
			int shu=f[j]/2;
			if(s%2==0&&f[j]%2==1)	shu++;
			//怎么理解?shu个j一定是连在一起的
			//一般有shu/2个j在奇数位,但如果第一个j在奇数位且有奇数个j就要多加一个
			t[j^x]+=shu,t[j]-=shu;
			s+=f[j]; 
		}
		for(int j=0;j<1024;j++)	f[j]=t[j];
	}
	int minn=1e9,maxx=0;
	for(int i=0;i<1024;i++)
	if(f[i])
	{
		maxx=max(maxx,i);
		minn=min(minn,i);
	}
	cout<<maxx<<" "<<minn;
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/107248687