链接地址: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;
}
915

被折叠的 条评论
为什么被折叠?



