找球号(三)
-
描述
-
xiaod现在正在某个球场负责网球的管理工作。为了方便管理,他把每个球都编了号,且每个编号的球的总个数都是偶数。有一天,xiaod发现少了一个球,你能帮他找出丢的那个球的球号吗?
-
输入
-
有多组测试数据。每组数据包括两行。
第一行是一个整数N(0<N<1000000),表示现在所剩的球数。
随后的一行是N个数,表示所剩的各个球的编号M(0<M<10^9)。
输出
- 对于每组数据,输出弄丢的那个球的球号。 样例输入
-
5 1 1 3 6 6 3 1 2 1
样例输出
-
3 2
-
有多组测试数据。每组数据包括两行。
/*这个题咋一看和做过的两个找球号的题目类似,但是给的内存太小了,根本做不了,从网上搜了一下,找到了这个位运算的巧妙方法,第一次看到了位运算的用处,以后要多加注意啊*/
我们先了解一下位异或的运算法则吧:
1、a^b = b^a。
2、(a^b)^c = a^(b^c)。
3、a^b^a = b。
对于一个任意一个数n,它有几个特殊的性质:
1、0^n = n。
2、n^n = 0。
所以可以通过每次异或运算,最后剩下的值就是出现奇数次的那个数字。
通过交换律和特殊性质,我们知道,输入的数中,个数为偶数的数相互异或运算必定为0,然后剩下那个出现奇数次的数(只剩下一个,其他的经过偶数次异或运算之后为0了已经),所以,这个数和0异或之后得到他本身,直接输出!
#include <stdio.h> int main() { int n,x,ans; while(scanf("%d",&n),n) { ans = 0; while(n--) { scanf("%d",&x); ans ^= x; } printf("%d\n",ans); } return 0; }
另外有一些C++的写法,暂时不太懂喽,先放在这留着!
思路:
为了节约内存,可以用STL里面的set,map等容器。
当容器里没有这个元素的时候,就插入这个元素,否则,删除这个元素。
最后,容器中肯定只剩下一个元素,便是我们所要的结果。
#include <set> #include <stdio.h> using namespace std; int main() { int n,x; set <int> S; while(scanf("%d",&n),n) { while(n--) { scanf("%d",&x); if(S.find(x) == S.end()) //没找到,插入 S.insert(x); else //找到了,删除 S.erase(x); } printf("%d\n",*S.begin()); S.clear(); } return 0; }