SDNU1541(二进制异或+统计两个出现的单独数字)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
const int maxn=1e6+5;
int num[maxn];
int T,n;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        int sum=0;
        int maxp=0,minp=0;
        for(int i=0; i<n; ++i)
        {
            scanf("%d",&num[i]);
            sum^=num[i];
        }
        int t=1;
        while((t&sum)==0)
        {
            t<<=1;
        }
        for(int i=0; i<n; ++i)
        {
            if((num[i]&t)==0)
            {
                maxp^=num[i];
            }
        }
        minp=sum^maxp;
        if(minp>maxp)
            printf("%d %d\n",maxp,minp);
        else
            printf("%d %d\n",minp,maxp);
    }
    return 0;
}

1.【算法思想】利用最终异或和二进制位从右到做第一个为1的位置:将整个数组所有值分为两类。一类数字在该位置二进制为0,另一类在该位置二进制为1。注意到两个单独出现的数字在这个位置的二进制位一定是不同的。(二进制异或相异为1)所以归为两类之中。两类数字分别异或的结果就是两个数字。

2.注意语法表达的错误(两处):

        while((t&sum)==0)
        {
            t<<=1;
        }

【知识点1】==运算符的优先级高于&因此,上面的语句不能写成下面的形式:

        while(t&sum==0)
        {
            t<<=1;
        }

【知识点2】t<<=1;是t二进制左移一位的正确表达式。

下面是错误的表达式:

  while((t&sum)==0)
        {
            t<<1;
        }

附上一张证明优先级的截图: 

猜你喜欢

转载自blog.csdn.net/qq_41658955/article/details/85042169