异或运算,两个数一样异或结果为0,不一样则为1。

所以如果一个数组中有两个只出现一次的数字,那么这两个数一定二进制中有一位为1。比如说a的二进制有一位是1,b的二进制那一位是0,所以按这一位来分组。

首先把所有数异或,得到两个数不同的那几位的二进制,我们称为tmp。

然后遍历数组,和tmp相同的分为一组,和tmp不同的为一组。这样刚好就给两个只出现过一次的数字分开了,并且也把出现两次的数字也分到一组了(因为出现两次

#include<iostream>
using namespace std;

const int N = 1010;
int a[N], res[N];
int n;

void findNumAppearOnce(int* arr, int& res1, int& res2) {
	int tmp = arr[0];
	for (int i = 1; i < n; i++) {
		tmp ^= arr[i];
	}
	int k = 1;
	while ((tmp & k) == 0) k <<= 1;
	for (int i = 0; i < n; i++) {
		if (a[i] & k) res1 ^= arr[i];
		else res2 ^= arr[i];
	}
}

int main() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	int res1 = 0, res2 = 0;
	findNumAppearOnce(a, res1, res2);
	cout << res1 << " " << res2;
	return 0;
}

=> 二进制相同 => &tmp一定相同)。