Loading docs/math/bit.md +48 −21 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ > \end{aligned} > $$ #### 取反 ## 取反 取反是对 1 个数 $num$ 进行的计算。 Loading Loading @@ -64,13 +64,13 @@ > > $$ > \begin{aligned} > &5&&=&&(101)_2\\ > &5\tt\,<<\,\rm2&&=&&(10100)_2\!\!\!&=&&\!\!\!20\\ > &5\tt>>\rm1&&=&&(10)_2&=&&2 > &5&&=&&(00000101)_2\\ > &5\tt\,<<\,\rm1&&=&&(00001010)_2\!\!\!&=&&\!\!\!20\\ > &5\tt>>\rm1&&=&&(00000010)_2&=&&2 > \end{aligned} > $$ 如上图,右移操作中末尾多余的 “1” 将会被舍弃。 在 C++ 中,右移操作中末尾多余的 “1” 将会被舍弃。而左侧较为复杂,对于无符号数,会在左侧补 0;而对于有符号数,则会用最高位的数补齐(Replicate most significant bit on left)。 注意,左移和右移是有返回值的,并非对 $num$ 本身进行操作。 Loading @@ -78,21 +78,36 @@ ## 位运算的应用 > `num << i` 相当于 $num$ 乘以 2 的 $i$ 次方,而 `num >> i` 相当于 $num$ 整除 2 的 $i$ 次方。 (位运算比 `%` 和 `/` 操作快得多) > (据 2018JSOI 夏令营,效率可以提高 60%) > > `num * 10 = (num<<1) + (num<<3)` > > `num & 1` 相当于取 $num$ 二进制的最末位,可用于判断 $num$ 的奇偶性,二进制的最末位为 0 表示该数为偶数,最末位为 1 表示该数为奇数。 > > ```cpp > //利用位运算的快捷的 swap 代码 > void swap(int a, int b){ > a = a ^ b; > b = a ^ b; > a = a ^ b; > } > ``` 如果 $num$ 是正数,`num << i` 相当于 $num$ 乘以 2 的 $i$ 次方,而 `num >> i` 相当于 $num$ 除以 2 的 $i$ 次方。 (位运算比 `%` 和 `/` 操作快得多) (据 2018JSOI 夏令营,效率可以提高 60%) !!! warning 为什么要强调是正数呢?考虑一下 `-1 >> 3` `num * 10 = (num<<1) + (num<<3)` `num & 1` 相当于取 $num$ 二进制的最末位,可用于判断 $num$ 的奇偶性,二进制的最末位为 0 表示该数为偶数,最末位为 1 表示该数为奇数。 ```cpp //利用位运算的快捷的 swap 代码 void swap(int a, int b){ a = a ^ b; b = a ^ b; a = a ^ b; } ``` 一个数的二进制表示可以看作是一个集合(0 表示不在集合中,1 表示在集合中)。比如集合 `{1, 3, 4, 8}`,可以表示成 `0b00000000000000000000000100011010`,十进制就是 $2^8+2^4+2^3+2^1=282$。 而对应的位运算也就可以看作是对集合进行的操作。 | 操作 | 集合表示 | 位运算语句 | | --- | --------------: | :-----: | | 交集 | $a \cap b$ | `a & b` | | 并集 | $a \cup b$ | `a | b` | | 补集 | $\bar{a}$ | `~a` | | 差集 | $a \setminus b$ | `~a` | | 对称差 | $a\triangle b$ | `a ^ b` | * * * Loading Loading @@ -211,6 +226,18 @@ } ``` #### 题目推荐 - 遍历一个集合的子集 ```cpp int b = 0; do { // process subset b } while (b = (b - x) & x); ``` ## 题目推荐 [CODEVS 2743 黑白棋游戏](http://codevs.cn/problem/2743/) ## 参考 位运算技巧:<https://graphics.stanford.edu/~seander/bithacks.html> Loading
docs/math/bit.md +48 −21 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ > \end{aligned} > $$ #### 取反 ## 取反 取反是对 1 个数 $num$ 进行的计算。 Loading Loading @@ -64,13 +64,13 @@ > > $$ > \begin{aligned} > &5&&=&&(101)_2\\ > &5\tt\,<<\,\rm2&&=&&(10100)_2\!\!\!&=&&\!\!\!20\\ > &5\tt>>\rm1&&=&&(10)_2&=&&2 > &5&&=&&(00000101)_2\\ > &5\tt\,<<\,\rm1&&=&&(00001010)_2\!\!\!&=&&\!\!\!20\\ > &5\tt>>\rm1&&=&&(00000010)_2&=&&2 > \end{aligned} > $$ 如上图,右移操作中末尾多余的 “1” 将会被舍弃。 在 C++ 中,右移操作中末尾多余的 “1” 将会被舍弃。而左侧较为复杂,对于无符号数,会在左侧补 0;而对于有符号数,则会用最高位的数补齐(Replicate most significant bit on left)。 注意,左移和右移是有返回值的,并非对 $num$ 本身进行操作。 Loading @@ -78,21 +78,36 @@ ## 位运算的应用 > `num << i` 相当于 $num$ 乘以 2 的 $i$ 次方,而 `num >> i` 相当于 $num$ 整除 2 的 $i$ 次方。 (位运算比 `%` 和 `/` 操作快得多) > (据 2018JSOI 夏令营,效率可以提高 60%) > > `num * 10 = (num<<1) + (num<<3)` > > `num & 1` 相当于取 $num$ 二进制的最末位,可用于判断 $num$ 的奇偶性,二进制的最末位为 0 表示该数为偶数,最末位为 1 表示该数为奇数。 > > ```cpp > //利用位运算的快捷的 swap 代码 > void swap(int a, int b){ > a = a ^ b; > b = a ^ b; > a = a ^ b; > } > ``` 如果 $num$ 是正数,`num << i` 相当于 $num$ 乘以 2 的 $i$ 次方,而 `num >> i` 相当于 $num$ 除以 2 的 $i$ 次方。 (位运算比 `%` 和 `/` 操作快得多) (据 2018JSOI 夏令营,效率可以提高 60%) !!! warning 为什么要强调是正数呢?考虑一下 `-1 >> 3` `num * 10 = (num<<1) + (num<<3)` `num & 1` 相当于取 $num$ 二进制的最末位,可用于判断 $num$ 的奇偶性,二进制的最末位为 0 表示该数为偶数,最末位为 1 表示该数为奇数。 ```cpp //利用位运算的快捷的 swap 代码 void swap(int a, int b){ a = a ^ b; b = a ^ b; a = a ^ b; } ``` 一个数的二进制表示可以看作是一个集合(0 表示不在集合中,1 表示在集合中)。比如集合 `{1, 3, 4, 8}`,可以表示成 `0b00000000000000000000000100011010`,十进制就是 $2^8+2^4+2^3+2^1=282$。 而对应的位运算也就可以看作是对集合进行的操作。 | 操作 | 集合表示 | 位运算语句 | | --- | --------------: | :-----: | | 交集 | $a \cap b$ | `a & b` | | 并集 | $a \cup b$ | `a | b` | | 补集 | $\bar{a}$ | `~a` | | 差集 | $a \setminus b$ | `~a` | | 对称差 | $a\triangle b$ | `a ^ b` | * * * Loading Loading @@ -211,6 +226,18 @@ } ``` #### 题目推荐 - 遍历一个集合的子集 ```cpp int b = 0; do { // process subset b } while (b = (b - x) & x); ``` ## 题目推荐 [CODEVS 2743 黑白棋游戏](http://codevs.cn/problem/2743/) ## 参考 位运算技巧:<https://graphics.stanford.edu/~seander/bithacks.html>