ACdream 1023 Xor

题目链接:http://acdream.info/problem?pid=1023

题意:给一个集合A,一个集合B,问可否存在一个数字C,使得A中所有元素和C做异或运算得到B集合。

小编做这道题的时候真的是很幸运,在草稿本上画字典树的时候,打了几个表一下子就被小编发现规律了,在验证的时候也没想太严谨,但是运气好的出奇的一A了。

首先,小编发现 一句话,n is odd,起初没有在意这句话,可能第一次看到它也觉得没什么吧,那我们先把这句话放到一边。

先来分析,A我们可以看成{a1,a2,a3……},B我们可以看成{a1^c,a2^c,a3^c……},写到这里小编在想异或运算是否有一个性质,那就是如果a^b = c,那么a^c = b,当时小编列了很多关于0和1是否相等的式子 ,在给别人讲的时候我也是说的因为0和1始终保持一个相等的个数,因为有0^1=1,1^1=1,0^0=0这些等式,但是小编刚刚发现麻烦了……这样讲似乎还误导了一些人,因为直接就可以证明:a^c = a^(a^b) = a^a^b = b,当时小编想,可不可以用字典树贪心在A集合中找到这个每一位对应的^c在B中的值,在列字典树的时候我想了一下该从高位开始列还是从低位开始列,于是先在草稿纸上写了样例的数据A{00,01,11}->B{01,10,11},突然发现A的总异或运算值x1^B的总异或运算值x2就等于c,一开始以为是个巧合,但是马上就得到了证明,因为B的总异或运算值x2就等于a1^c^a2^c^a3^c……那么就等于x1^c^c^c^c^c……明显当c的个数是偶数的话就是0,奇数就是1,这个时候那句n is odd就有用了,所以x1^x2的结果一定等于c。

但是这个计算结果又一定是正确的吗,我们这样做是建立在有c的情况下,如果c存在一定满足,如果c不存在只是满足x1 ^ c=x2,但不满足每一位相等,就不能这样计算了,我们还得证明A的每一位^c之后和B一样,这个时候应该是队友没听懂我的思路,胡乱说可不可以加起来判断,当时听了觉得有道理……试了一下,就真的A了……(运气真的不是一般的好)。

这道题从我读题到A掉只用了不到5分钟的时间,中间各种巧合,现在写题解的时候才发现还是有很多值得思考的地方,比如异或运算的性质之类的。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100005;
int a[maxn],b[maxn];
int main()
{
	int n;
	while(scanf("%d",&n) !=EOF)
	{
		int x1 = 0,x2 = 0,tmp;
		int sum1 = 0,sum2 = 0;
		for(int i=1; i<=n; i++)
		{
			scanf("%d",&a[i]);
			x1 ^= a[i];
		}
		for(int i=1; i<=n; i++)
		{
			scanf("%d",&b[i]);
			x2 ^= b[i];
			sum2 += b[i];
		}
		x1 ^= x2;
		for(int i=1; i<=n; i++)
			sum1 += x1^a[i];
		if(sum1 == sum2) printf("%d\n",x1);
		else printf("-1\n");
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值