二进制
知识:
‘<<’ 左移 ‘>>’右移 ‘~’ 非 ‘^’ 异或 ‘&’ 与 ‘|’或
例:
a<<3 a * 2^3; 将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃
a>>3 a / 2^3; 将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
~a a的二进制位每位(0变1, 1变0)
a^b 把a与b的相同位比较 相同变0 相异变1
a&b 把a与b的相同位比较 相同变1 相异变0
a|b 把a与b的相同位比较 有1变1 全0变0
复合赋值运算符:
&= 例:a &= b 相当于a=a & b
|= 例:a |= b 相当于a=a | b
>>= 例:a >>= b 相当于a=a >> b
<<= 例:a <<= b 相当于a=a << b
^= 例:a ^= b 相当于a=a ^ b
问题: 一组数据中只有一个数出现一次,其他的数都出现 X 次,求出现一次的这个数。
解决:每个数都可以写成二进制数,当同一个数出现X次时,它二进制表达式的’1‘在相同位也会出现X次。
所以有一个结论:通过计算二进制表达式的每个位上的累计值是否可以整除X,
就知道那单独的一个数在这个位上是0还是1
#include <iostream> #include <cstdio> #include <cstring> using namespace std;
int s[32]; //记录二进制表达式每个位上1出现的次数。 int n, x; //n代表一共有n个数,x代表重复出现的数的出现次数 void zh_(int a){ for(int i=0; i<32; i++) s[i] += ((a>>i) & 1); //统计a的二进制表达式各个位是否为1,s数组记录 } void f_one(){ int i, one=0; for(i=0; i<32; i++) if(s[i]%x) //位上的统计值不能整除x one += (1<<i); printf("the only one is %d\n", one); } int main(){ int i, a; while(scanf("%d%d", &n, &x) != EOF){ memset(s, 0, sizeof(s)); //每次开始时要把s数组清0 for(i=0; i<n; i++){ scanf("%d", &a); zh_(a); } f_one(); } return 0; }

浙公网安备 33010602011771号