题目链接:http://acm.zzuli.edu.cn/problem.php?id=1519
时间限制: 2 Sec 内存限制: 16 MB
题目描述
小P最近人生得意,去参加了一次相亲大会,相亲大会上每个人有一个密码牌(密码牌上的密码是一个正整数m,m<231 ),相互之间在交流之前先交换密码牌,密码牌上的密码可能相同,也可能不同,如果相同,两人牵手离开,如果不保同,各自再寻找下一位,保证最后只有1个人或2个人留下来。
输入
第一行两个数 n,k (n≤3000000,1≤k≤2),n表示参加相亲大会的人数,接下来 n行每行一个正整数表示相亲大会上每一个人的密码,k表示最后留在相亲大会的人数。
输出
从小到大输出一行 k个数,表示相亲不成功留在相亲大会人的密码,中间用空格分隔。
样例输入
3 1
2
2
2
样例输出
2
提示
对于40%的数据,保证 k=1。
对于20%的数据,保证n≤100
对于100%的数据,保证 n≤3000000,ai<2^31。
解题思路
因为数据太大我们不能用一般的方法,这道题其实就是在一堆数中找出k个出现奇数次的数,其余都出现偶数次。解析详见https://blog.csdn.net/lzyws739307453/article/details/88133245
#include <iostream>
int n, arr[3000005];
void FindNum(int len, int k) {
int s = 0;
for (int i = 0; i < len; i++)
s ^= arr[i];
if (k == 1) {
printf("%d\n", s);
return ;
}
int s1 = s, s2 = s, m = 0;
while (!(s1 & 1)) {
s1 >>= 1;
m++;
}
for (int i = 0; i < len; i++)
if ((arr[i] >> m) & 1)
s ^= arr[i];
if (s < s ^ s2)
printf("%d %d\n", s, s ^ s2);
else printf("%d %d\n", s ^ s2, s);
}
int main() {
int n, k;
while (~scanf("%d%d", &n, &k)) {
for (int i = 0; i < n; i++)
scanf("%d", &arr[i]);
FindNum(n, k);
}
return 0;
}