链接地址:http://ac.nbutoj.com/Problem/view.xhtml?id=1314
是不是想起了筷子大作战这一题?
(1) 那题的意思就是有很多筷子,除了其中一只,其他都是成对等长出现的。
直接异或,所有相同的数都会被抵消(异或运算中,相同位置值相等的结果为0,就是说所有成对出现的都会最终成为0),最后的结果自然是那个落单的数了。
然后,我们来看这题。
(2) 这题的意思是有很多把钥匙,每把钥匙上都有编号。有相同编号的两把钥匙都要依次排除,这样最后肯定剩下2把钥匙,那么这两把钥匙的编号是不一样的,就是答案所要的钥匙。
如果是有两个互不相同的数,我们可以把他分成两个段,段名分别为A,B。这里为了解释方便,给出10个数,分别为a,a,b,b,c,c,d,d,e,f;
现在我们知道,只要A段和B段能满足上面的(1)所说的情形,即两个不同的数(e,f分别在A,B段内)分别在不同的段内,其他的数成对出现在相同的段内,就可以仿照(1)得到结果。举个例子A(a,a,b,b,e);B(c,c,d,d,f);
是不是觉得很难分呢?怎么才能按照上面的形式分开成为A,B呢?别急,注意咯,我上面说的是其他数成对出现,并不是一定要对半分,也可以是A(a,a,b,b,c,c,d,d,e);B(f);或者A(a,a,b,b,c,c,e);B(d,d,f);是不是有点头绪了?没有?别紧张,往下看,快搞定了
我们先来想想如何分e,f。首先,他们本身不相等,所以e^f的值一定不为0,也就是说,e^f的值转换成2进制,一定至少有一个1出现。好的,我们从右向左找第一次出现1的位置,将所有数中,这个位置是1的放进A,是0的放进B。OK,完全符合我们对AB段的要求,再从A,B中分别异或找出e,f不是问题!
出题代码:
是不是想起了筷子大作战这一题?
(1) 那题的意思就是有很多筷子,除了其中一只,其他都是成对等长出现的。
直接异或,所有相同的数都会被抵消(异或运算中,相同位置值相等的结果为0,就是说所有成对出现的都会最终成为0),最后的结果自然是那个落单的数了。
然后,我们来看这题。
(2) 这题的意思是有很多把钥匙,每把钥匙上都有编号。有相同编号的两把钥匙都要依次排除,这样最后肯定剩下2把钥匙,那么这两把钥匙的编号是不一样的,就是答案所要的钥匙。
如果是有两个互不相同的数,我们可以把他分成两个段,段名分别为A,B。这里为了解释方便,给出10个数,分别为a,a,b,b,c,c,d,d,e,f;
现在我们知道,只要A段和B段能满足上面的(1)所说的情形,即两个不同的数(e,f分别在A,B段内)分别在不同的段内,其他的数成对出现在相同的段内,就可以仿照(1)得到结果。举个例子A(a,a,b,b,e);B(c,c,d,d,f);
是不是觉得很难分呢?怎么才能按照上面的形式分开成为A,B呢?别急,注意咯,我上面说的是其他数成对出现,并不是一定要对半分,也可以是A(a,a,b,b,c,c,d,d,e);B(f);或者A(a,a,b,b,c,c,e);B(d,d,f);是不是有点头绪了?没有?别紧张,往下看,快搞定了
我们先来想想如何分e,f。首先,他们本身不相等,所以e^f的值一定不为0,也就是说,e^f的值转换成2进制,一定至少有一个1出现。好的,我们从右向左找第一次出现1的位置,将所有数中,这个位置是1的放进A,是0的放进B。OK,完全符合我们对AB段的要求,再从A,B中分别异或找出e,f不是问题!
出题代码:
#include <set> #include <map> #include <list> #include <stack> #include <queue> #include <cmath> #include <cstdio> #include <vector> #include <iomanip> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; #define N 1000010 int a[N]; int b[N]; int c[N]; int main() { int n; //freopen("data.in", "r", stdin); //freopen("data.out", "w", stdout); while (~scanf("%d", &n)) { int s = 0; for (int i = 0; i < n; i++) { scanf("%d", &a[i]); s ^= a[i]; } int p; for (int i = 0; i < 32; i++) { if ((s >> i) % 2 == 1) { p = i; break; } } int bn, cn; bn = cn = 0; for (int i = 0; i < n; i++) { if ((a[i] >> p) % 2) b[bn++] = a[i]; else c[cn++] = a[i]; } int s1, s2; s1 = s2 = 0; for (int i = 0; i < bn; i++) { s1 ^= b[i]; } for (int i = 0; i < cn; i++) { s2 ^= c[i]; } printf("%d %d\n", min(s1, s2), max(s1, s2)); } return 0; }