开关性是异或运算最重要的性质--同一个数异或两次以后相当于没有异或。
另外,异或还满足交换律,0与任何数异或的结果还是该数。
HDU5650点击打开原题链接
题目大意:给一个集合,将该集合的所有子集内的所有元素进行异或运算,输出其结果
Input
#include
int main()
{
int t, x, n;
scanf( "%d", &t);
for ( int i = 1; i <= t; ++ i){
scanf( "%d", &n);
for ( int j = 1; j <= n; ++ j){
scanf( "%d", &x);
}
if ( n == 1){
printf( "%d\n", x);
}
else
printf( "0\n");
}
return 0;
}
当集合中所有元素在子集中出现的总次数均为2^(n - 1),只有当n=1时出现技术次,所以直接判断n是否等于1即可。
ZZUOJ10450: 找数点击打开原题链接
题目大意:
给一堆数,其中只有两个数只出现一次,其他的均出现两次,找出这两个数,并按从小到大的顺序输出
10
1 2 2 3 4 4 5 5 6 6
1 3
给出代码:
#include
#define maxn 2000010
int a[maxn];
int main()
{
int n, t, x, y, z;
scanf( "%d", &n);
x = 0;
for ( int i = 0; i < n; ++ i){
scanf( "%d", &a[i]);
x ^= a[i];
}
x &= -x;
y = z = 0;
for ( int i = 0; i < n; ++ i){
if ( x & a[i])
y ^= a[i];
else
z ^= a[i];
}
if ( y > z){
t = y; y = z; z = t;
}
printf( "%d %d\n", y, z);
return 0;
}
首先利用异或运算得到的x便是这两个数异或的结果,将x与-x异或便得到x补码中位最低的1所对应的值(x中该位为1,则这两个数中必然只有1个该位为1,同树状数组中lowbit原理)
然后利用其,将所有数分为两堆,这两个数位于不同的堆,然后将两堆异或,得到的两个结果便是这两个数。