GDUT新生赛—H

Problem H: 《为什么会变成这样呢》

Description

“第一次有了喜欢的人,还得到了一生的挚友,两份喜悦互相重叠,这双重的喜悦又带来了更多更多的喜悦,本应已经得到了梦幻一般的幸福时光,然而,为什么,会变成这样呢?”双重的喜悦感却无法带来更多的幸福,现在,雪菜在很多喜悦感之中只想要得到两份不重叠的喜悦感(其他的喜悦感都是重叠的),你能帮她找出这两份不同的喜悦感是多少吗?

Input

第一行一个整数T,代表数据的组数(1<=T<=10),接下来T组数据,每组数据的第一行是一个整数n(1<=n<=1000000),第二行是n个整数ai(0 <= ai <= 1000000000)代表喜悦感,每两个整数之间有一个空格,题目保证有且仅有两个不同的整数出现一次,其他的整数都是出现两次。

Output

对于每组数据,输出两个整数,分别代表两份不同的喜悦感,中间有一个空格,并且喜悦感较小的先输出。

Sample Input

2
6
2 2 1 1 3 4
4
1 1 3 4

Sample Output

3 4
3 4

【分析】

一道经典题的拓展,我做过的题目是只有一个数出现一次。
如果只有一个数出现一次,那么很简单,整个数组异或一遍,得出的结果就是出现过一次的题目。
只需要记得
0A=A    A⊕A=0
A⊕B=B⊕A   
(A⊕B)⊕C=A⊕(B⊕C)
这道题因为有两个数出现过一次。
所以不能简单的异或整个数组,这个时候异或整个数组。得出的结果是这两个数的异或结果。
那么我们可以考虑,把这n个数分成两组,分别异或,就可以得到这两个数。
显然,出现两次的数不用考虑,因为它们不管分在哪一组,都对结果没有任何影响,所以要考虑的是,如何将这两个数分到两组中去。
这两个数异或结果中为0的位说明两个数在这个二进制位上表示相同,那么只要找到第一个表示不同的位置,就可以将这两个数区分开了。
找到第一位为1的位置xx
然后对对每个数的二进制位中xx这个位置进行判断,0的为一组,1的为一组。两组分别异或就可以求出答案。
【代码】
#include <stdio.h>
int a[2010000];
int main()
{
int pp;scanf("%d",&pp);
while (pp--)
{
int n;scanf("%d",&n);
  int ans=0;
   int A=0,B=0;
   for (int i=0;i<n;i++)
   {
    scanf("%lld",&a[i]);
       ans^=a[i];
   }
int xx=0;
while (ans)
{
if (ans%2==1) break;
xx++;
ans/=2;
}
   for (int i=0;i<n;i++)
   {
       int x=1 & (a[i] >> xx); 
       if (x)
           A^=a[i];
       else
           B^=a[i];
   }
   if (A>B) {int t=A;A=B;B=t;}
   printf("%d %d\n",A,B);
}
return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值