数论-位运算 xmu1080 The Lost Two Cards

1080: The Lost Two Cards

Time Limit: 2500 MS   Memory Limit: 64 MB
Submit: 27   Solved: 0
[ Submit][ Status][ Web Board]

Description

  Having signed a new contract, ArXoR was facing a new task. Given n cards each of which is labeled with an integer bounded in [-2^31,2^31 - 1], the task is to make a duplicate copy of these n cards. As usual, this dull job was assigned to TheBeet. After he finished duplicating, he brought the 2n cards to ArXoR. But after checking these cards again, they found that two cards was lost. It is easy to make another duplication of a card, but not easy to find out which card should be duplicated again. Could you help these two poor guys , especially, TheBeet.

Input

  The input contains a single case. The case begin with a integer n bounded in [3, 1000000]. 
  Then 2 * n - 2 lines follows, as mentioned above, each of which indicates the integer on the card in TheBeet and ArXoR's hands.

Output

  You should output a single line containing two numbers, the lost cards you have found, with the smaller one at first. Output "poor"(without quote) if the two cards are equal, that means these two poor guys would never find them again.

Sample Input

4
35
4
2
4
35
7

Sample Output

2 7


题意:

从若干个数中找到两个只出现一次的数,其他数字均会出现两次,若所有数字都出现了两次,输出"poor"

思路:

一开始联想到的是另一道题,从若干数中找到一个只出现一次的数,其他数字均会出现两次,全异或即可;再看看题目数据范围想到了快速排序,把所有数字排序一次,相等数字必然相邻,时间复杂度O(nlogn)
但本题采用异或有最优解,时间复杂度O(n),思路是先对所有数字做一次异或,结果为零时输出"poor",不为零时check为a^b,用dis变量寻找check中的1位,即a,b数字相异的位,再次遍历,根据相异位置把所有数分成两堆,各自异或即可


代码:

#include <stdio.h>
constint maxsize = 1000000;
intmain(){
    intarr[maxsize];
    intn;
    scanf("%d", &n);
    n = 2 * n - 2;
    intcheck = 0;
    for(inti = 0; i < n; ++i){
        scanf("%d", &arr[i]);
        check = check^arr[i];
    }
    if(!check){
        printf("poor\n");
    }
    else{
        inta = 0, b = 0, dis = 1;
        while(!(check & dis)) dis = dis << 1;
        for(inti = 0; i < n; ++i){
            if(arr[i] & dis)
                a = a^arr[i];
            elseb = b^arr[i];
        }
        if(a<b) printf("%d %d\n", a, b);
        elseprintf("%d %d\n", b, a);
    }
    return0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值