二进制

知识:
    ‘<<’ 左移   ‘>>’右移   ‘~’ 非   ‘^’ 异或   ‘&’ 与  ‘|’或 
    例: 
      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; }

 

posted @ 2015-09-22 15:26  马晨  阅读(138)  评论(0)    收藏  举报