二进制集合操作
二进制集合操作
一个数的二进制表示可以看作是一个集合(
| 操作 | 集合表示 | 位运算语句 | 
|---|---|---|
| 交集 | a & b | |
| 并集 | a | b | |
| 补集 | ~a(全集为二进制都是 1) | |
| 差集 | a & (~b) | |
| 对称差 | a ^ b | 
在进一步介绍集合的子集遍历操作之前,先看位运算的有关应用例子。
模 2 的幂
一个数对 
=== "C++"
```cpp
int modPowerOfTwo(int x, int mod) { return x & (mod - 1); }
```=== "Python"
```python
def modPowerOfTwo(x, mod):
    return x & (mod - 1)
```于是可以知道,
事实上,对于一个正整数 
借此可以判断一个数是不是 
=== "C++"
```cpp
bool isPowerOfTwo(int n) { return n > 0 && (n & (n - 1)) == 0; }
```=== "Python"
```python
def isPowerOfTwo(n):
    return n > 0 and (n & (n - 1)) == 0
```子集遍历
遍历一个二进制数表示的集合的全部子集,等价于枚举二进制数对应掩码的所有子掩码。
掩码是一串二进制码,用于和源码进行与运算,得到屏蔽源码的若干输入位后的新操作数。
掩码对于源码可以起到遮罩的作用,掩码中的 
给定一个掩码 
或者使用更紧凑的 for 语句:
这两段代码都不会处理等于 
接下来证明,上面的代码访问了所有 
假设有一个当前位掩码 
为了使 
这两步操作等价于切割掩码 
因此,该算法按降序生成该掩码的所有子掩码,每次迭代仅执行两个操作。
特殊情况是 
使用 
遍历所有掩码的子掩码
在使用掩码动态编程的问题中,有时会希望对于每个掩码,遍历掩码的所有子掩码:
这样做可以遍历大小为 
接下来证明,该操作的时间复杂度为 
考虑第 
- 在掩码 - 在 - 在 
总共有 
还有一种证明方法是:
如果掩码 
上面的和等于使用二项式定理对 
参考资料
本页面主要译自博文 Перебор всех подмасок данной маски 与其英文翻译版 Submask Enumeration。其中俄文版版权协议为 Public Domain + Leave a Link;英文版版权协议为 CC-BY-SA 4.0。
习题
本页面最近更新:2/3/2023, 12:00:00 AM,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用