51Nod 2107 二个奇数次(位运算)

2107 二个奇数次

1.0 秒 131,072.0 KB
输入一个长度为n的数组,考虑所有不同的数字,有且只有2个数字出现了奇数次。

比如对于1 2 3 1 2 3 1 2,我们考虑所有不同的数字1 2 3,有且只有1,2出现了奇数次(均为3次)

输出这两个出现了奇数次的数字。

先输出这两个数字中较小的,再输出较大的。

1 <= n <= 100000

1 <= a[i] <= 10^9

输入

第一行一个整数n,
接下来一行n个整数,表示输入的数字。

输出

一行2个数字,表示出现了奇数次的数字,先输出小的,再输出大的。

输入样例

8
1 2 3 1 2 3 1 2

输出样例

1 2

解题思路:之前我们做过一个奇数次,即给定n个数,有且只有一个数出现了奇数次,输出这个数,在做那个题的时候直接一直异或运算就可以得到想要的数字(因为n^n等于0,而0和任何数异或都是数字本身,所以就很好求),这个题要求出现奇数次的两个数,肯定不能一直异或吧…思路:还是先将所有数异或在一起,最后一定会得到一个数,这个数是要求的两个数异或在一起,然后分成两组去求这两个数,具体怎么分呢?假设两个数异或在一起的二进制数R是110111000,我们知道异或以后1的位置就是两个数不一样的位置。我们进行这样一个操作:int lowbit=R&(-R),这个操作的用处在于找出最低位1的位置。R是110111000,而-R是001001000,(数字在计算机中是以补码的形式存储的)两个数&在一起,得出来的是1000这就是两个数不同的地方最低位1的位置,我们分两组:这一位是1的一组,0的一组,然后异或在一起,就很容易得到了。代码实现:

#include <bits/stdc++.h>
using namespace std;
const int _max=1e5+5;
int s[_max];
int main()
{
	int n,r=0;
	int a=0,b=0;
	cin>>n;
	for(int i=0;i<n;i++)
	  cin>>s[i];
	for(int i=0;i<n;i++)
	  r^=s[i];
	int lowbit=r&(-r);//找最低位1的位置
	for(int i=0;i<n;i++)
	  if(s[i]&lowbit)//分成两组分别异或
	    a^=s[i];
	  else
	    b^=s[i];
	cout<<min(a,b)<<" "<<max(a,b)<<endl;
	return 0;	  
}
posted @ 2020-02-20 22:59  Hayasaka  阅读(180)  评论(0编辑  收藏  举报