位运算之巧解
Posted acgoto
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了位运算之巧解相关的知识,希望对你有一定的参考价值。
上班打卡
Time Limit: 2000/1000ms (Java/Others)
Problem Description:
某公司上班使用打卡制度,员工需要在打卡机器上打入和打出才算上班。每个员工都有自己对应编号K,编号为一个整数(1 <= K <=50000),某天有一员工忘记了一次打出。现在给你当天员工的打卡信息,你能找出该员工的编号吗?
Input:
输入包含多组测试,第一行包含数字N,表示公司的人数(1<=N<=50000)。第二行有2N-1个数,两两之间有空格,表示所有员工的打卡记录。输入N为0则退出程序,不做输出。
Output:
对于每组测试,单独一行输出忘记打卡员工的编号。
Sample Input:
4 10 12 9 12 250 9 10
Sample Output:
250
解题思路:给出2n-1个数,其中有n个数出现的次数都为2,剩下的1个数出现的次数为1,要求快速找出这个数。通过异或运算的特点可知,①自己异或本身的值为0,②任何数和0异或都为其本身。因此异或所有出现次数为2的数最终的值为0,那么就只剩下出现次数为1的元素。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,x,ans; 4 int main(){ 5 while(cin>>n&&n){ 6 n=2*n-1,ans=0; 7 while(n--){cin>>x;ans^=x;} 8 cout<<ans<<endl; 9 } 10 return 0; 11 }
小白刷分记(二)
Time Limit: 2000/1000ms (Java/Others)
Problem Description:
小白最近刷听力,刷出了一个大麻烦。不知为何刷出了负分,小白只能向大白求助。 无奈大白翻车了。所以小白向小光师公求助,小光师公说只要你帮我解决了下面这道题目, 我就帮你刷回正分。无奈小白不会,只能交给聪明的你来解决了。 数组A中,除了某一个数字x之外,其他数字都出现了三次, 而x出现了一次。请给出最快的方法找到x。
Input:
先输入n,表示要输入n个数字。( 0< n < 10^8) 然后输入n个数字m。(-10^8)< m <(10^8)
Output:
输出x
Sample Input:
10 2223 1 1 2223 1 -111 1 2223 1 1 4 5 5 5 -6
Sample Output:
-111 -6
解题思路:给出n个数,其中有(n-1)/3个数出现的次数都为3,剩下的1个数出现的次数为1,要求快速找出这个数。考虑每个数的二进制,因为每个数出现的次数都为3,所以其二进制每位bit上1的个数肯定为3的倍数,否则就是出现次数为1的数在这个二进制bit位上贡献出多余的1。因此,先将每个数转化成32位的二进制,并且统计每位bit上1的个数,然后累加某位bit上不能被3整除的十进制数1<<bit后即可得到出现次数为1的数。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,x,ans,bits[32]; 4 int main(){ 5 while(~scanf("%d",&n)){ 6 ans=0;memset(bits,0,sizeof(bits)); 7 for(int i=1;i<=n;++i){ 8 scanf("%d",&x); 9 if(!x)continue; 10 for(int j=0;j<32;++j)bits[j]+=((x>>j)&1);//要用右移操作,便于正确计算和避免溢出 11 } 12 for(int i=0;i<32;++i) 13 if(bits[i]%3!=0)ans+=(1<<i);//累加二进制上对应的值 14 printf("%d ",ans); 15 } 16 return 0; 17 }
以上是关于位运算之巧解的主要内容,如果未能解决你的问题,请参考以下文章