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< ai ≤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 |aj & 2i ==1}中必然只包含 x,y中的一个(假设是 x ) ,其他元素皆为有相同的元素(juruo语文差...自行体悟吧),而其他数字的 xor 操作等于没有,所以 A 中所有元素的 xor 则为 x,
再根据 x^y^x=y 即可求出 y.
时间,空间复杂度皆为 O( n ) .
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }