题意:已知九个数:x1 xor m,x2 xor m......x8 xor m,(x1+x2+....+x8) xor m;求出m
分析:
1.深入了解运用位运算:加法、异或的特性。异或的一些特性如:异或偶数次同样的数等于没做任何操作;若 a=b^c 则:b=a^c 、c=a^b
2.熟练运用位运算符号:& 和 ^ 比如用 &1 从十进制的角度可以判断一个数是奇数还是偶数,从二进制位的角度也可以得到一个数的最末位是1还是0
3.理解运用一位运算符:>> 和 <<
这道题是从低位开始一位一位的计算。主要思路是计算这八个数的最末位为1的数的个数记为 cnt ,再加上进位(初始设为0)设和为 x, 如果x是奇数,则这八个数加起来的和的末位也一定是1;如果是偶数,则末位一定是0,。这时候再根据已知的这八个数的和异或m的值得末位就可以反推出m的末位(用上面的异或的特性二)然后这九个数都右移一位,进位也右移一位,即把高位的移到末位,然后循环,直到所有数都为0且进位也为0.
不清楚就好好想想。
代码:
#include<cstdio>
#include<iostream>
#define INF 1<<31
using namespace std;
int t,a[10];
int main()
{
cin>>t;
while(t--){
for(int i=0;i<9;i++) cin>>a[i];
int c=0,m=0;
int k=0;
while(1){
int pp;
for(pp=0;pp<9;pp++)
if(a[pp]!=0) break;
c>>=1; // 位运算进位跟着移动
if(!c&&pp==9) break;
int cnt=0;
for(int i=0;i<8;i++) if(a[i]&1) cnt++; // &1判断奇偶
int x=cnt&1;
int y=(x^(c&1)^(a[8]&1)); //异或运算的循环特性
if(y){
c+=8-cnt; //求出原来的数中真正的1的个数得到进位
}
else c+=cnt;
m+=y<<k; // <<运算符的运用
k++;
for(int i=0;i<9;i++) a[i]>>=1; //位运算时常用的移动
}
cout<<m<<endl;
}
}