White

今天考试的第二题,虽然是已到 大水题 ,但由于本人是 蒟蒻,因此并不会做...

并不明白为何题目叫 white ,,,

-------------------------废话到此结束------------------------------------------

题目大意:

一数列有 n ( n 为 偶数 ) 个数 ,其中只有两个数 只有一个,如下面数列:

4 2 3 5 4 3 2 1

共 8 个数 ,其中 2 ,3,4 都出现了 2 次,只有 1,5 出现了一次.

现在给出一上述数列 {an} ,求出其中的出现次数为一次的数字.

 

对于10% 的数据 , 有N ≤100 ,

 

对于另外40% 的数据,有N ≤100000 ,

 

对于100% 的数据 , 有N ≤107  , 0< a≤2147483647 .

 

 

 

• 10%做法:别搜得太放荡就行...

• 50%做法:sort()一遍,然后 n2枚举.

 

• ?%做法("高级"暴力):

 

  由于 n <=1e7,而a[i]在int 范围内,因此这个数列是很稀疏的,所以可以先 mod 一个较大的质数,而后 n2  枚举.

   (出题人的奇思妙想...juruo不懂)

 

•100%做法:

  既然除了答案 x,y 之外,所有数字都被重复两遍,那么  a[1]^a[2]^a[3]^......^a[n] 即为 x^y ;

  设 sum=x^y ,若 sum 的二进制从右向左第一个 " 1 " 是在第 i 位 , 那么 x 和 y 中 必定 有一个数字的二进制对应的第 i 位为0,另一个为 1 ;

  所以集合 A={aj |a& 2==1}中必然只包含 x,y中的一个(假设是 x ) ,其他元素皆为有相同的元素(juruo语文差...自行体悟吧),而其他数字的 xor 操作等于没有,所以 A 中所有元素的 xor 则为 x,

  再根据 x^y^x=y 即可求出 y.

  时间,空间复杂度皆为 O( n ) .

 

 

 1 //Copyright(C)Sunshine.
 2 //2017.10.28
 3 #include<cstdio>
 4 #include<algorithm>
 5 #define pc(c) putchar(c)
 6 const int N=1e7+1;
 7 int fig[N];
 8 inline int read()
 9 {
10     int f=1,x=0;char c=getchar();
11     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
12     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
13     return f*x;
14 }
15 inline void write(int x)
16 {
17     if(x<0)pc(45),x=~(x-1);
18     int s[19],top=0;
19     while(x)s[++top]=x%10,x/=10;
20     if(!top)s[++top]=0;
21     while(top)pc(s[top--]+48);
22 }
23 int main()
24 {
25     int n=read(),sum=0;
26     for(int i=1;i<=n;i++)fig[i]=read(),sum=sum^fig[i];
27     int ans[3]={0,0,0};
28     for(int i=0;i<sum;i++)
29         if(sum&(1<<i))ans[0]=(1<<i);
30     for(int i=1;i<=n;i++)
31         if(fig[i]&ans[0])ans[1]=ans[1]^fig[i];
32     ans[2]=ans[1]^sum;
33     if(ans[1]>ans[2])std::swap(ans[1],ans[2]);
34     write(ans[1]);
35     pc(32);
36     write(ans[2]);
37     return 0;
38 }
xor
posted @ 2017-10-28 21:31  昤昽  阅读(170)  评论(0编辑  收藏  举报