0x00 基础算法和常用技巧

0x01位运算

与、或、异或

运算符 解释 例子
& 对应位上两个数都为\(1\)结果为\(1​\),反之为\(0​\) 101 & 001 = 001
| 对应位上两个数有一个为\(1\)结果为\(1\),反之为\(0\) 101 | 010 = 111
异或^ 对应位上两个数不同为\(1\),反之为\(0\) 101 ^ 100 = 001

特别的异或的逆运算还是异或,( a ^ b ) ^ b = a

取反

~一个数的每一位取反,~ 1001 = 0110

注意这里的~是按位取反,!是逻辑取反

左移、右移

左移(>>)把二进制的每一位向左移动,多余的舍弃,右侧补0注意可能会移到符号位上,导致变成负数

右移(<<)把二进制的每一位向右移动,多余的舍弃,左侧补0

注意左移右移的运算优先级低于加减,所以a << 1 + 1 = a << ( 1 + 1 )

位运算的应用

代替乘除

a << i等价于\(a \times 2^i\)

a >> i等价于\(a\div 2^i\)

a * 10 = ( a << 3) + ( a << 1 )

集合运算

如果用二进制数来表示集合,还有一些集合运算

操作 集合表示 位运算操作
交集 $a \cap b $ a & b
并集 \(a \cup b\) a | b
补集 \(\overline a\) ~ a

枚举子集

扫描二维码关注公众号,回复: 7861313 查看本文章
for( register int i = x ; i ; i = ( i - 1 ) & x );

优化常数

下面的写法,在一定程度上可以优化常数

判断奇偶

if( x & 1 ) = if( x % 2 )

交换两个数

inline void swap( int & x , int & y ) { x ^ y ^ x ^ y;}

判断两个数符号是否相同

inline bool isSameSign(int x, int y) {  // 有 0 的情况例外
  return (x ^ y) >= 0;
  // true 表示 x 和 y 有相同的符号,false 表示 x,y 有相反的符号。
}

求平均值

inline int getAverage( int x , int y ) { return (x + y) >> 1; }

猜你喜欢

转载自www.cnblogs.com/Mark-X/p/11863887.html