摘要:有n根(n为奇数)长短不一的筷子,里面可以凑成(n-1)/2双筷子,只剩下一根不能凑对,问那根不能凑对的筷子有多长。
乍听起来好像不难,桶是一个好东西,可是一看数据:对于100%的数据,N<=10000001,筷子长度不大于 10^9。
桶直接就淘汰掉了。
但是其实我第一次A用的却是桶,直接上代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,t,a[10000010]; int main(){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&t); a[t]++;//桶计算 if(a[t]==2){ a[t]-=2;//如果凑成一对了就把他减去 } } for(long long i=0;i<=1000001;i++){ if(a[i]>0){ printf("%d\n",i);//如果在遍历桶的时候找到了那根落单的筷子就直接输出。 break; } } return 0; }
靠的是一股巧劲儿。
直到我做完这题不久后,我得知了一个神奇的东西:^异或符号
0^0=0,0^1=1 0异或任何数=任何数
1^0=1,1^1=0 1异或任何数-任何数取反
任何数异或自己=把自己置0
异或运算符的特点是:数a偶数次异或同一个数b(例如:a=a^b^b)仍然为原值a。
所以我们只要在输入的时候一直异或,就可以得到落单的那跟筷子的长度(我刚知道的时候像发现了新大陆一样)。
代码如下:
#include<iostream> #include<cstdio> using namespace std; int n,m,ans=0; int main(){ scanf("%d",&n);//输入一共有几根筷子 for(int i=0;i<n;i++){ scanf("%d",&m);//输入每根筷子的长度 ans^=m;//异或大法好,只要一直这样最后得出来的结果肯定是落单的那根筷子的长度。 } cout<<ans<<endl; return 0; }
这样写简单明了,比起我那个桶强多了,然后感谢这道题让我知道了^,以后在做别的题的时候也可以用到。