bitset 可以用来进行一些玄学优化,所以又被称为骗分神器。还能用来卡常

它可以巧妙利用位运算跑得快的优势,而且没有普通整数最高 64 位的限制。(只需要在初始化时定义长度)
而且很全能,还可以当 bool 数组使用(可以使用 [] 运算符直接访问元素)。
你能把整数转成 bitset,当你又想转成整数时也能轻松转换。与字符串互转也不在话下。

初始化

#include <bitset>
std::bitset<N> b;    // 初始化一个长度为 N 的 bitset,名称为 b

还有其他初始化方式

using namespace std;
bitset<N> b(u);            // 作为一个无符号 int 的副本初始化
// 以下需包含 string 头文件
bitset<N> b(s);            // 作为一个 string 的副本初始化
bitset<N> b(s, pos);    // 作为 s 中从位置 pos 开始位的副本初始化
bitset<N> b(s, pos, n);    // 作为 s 中从位置 pos 开始的 n 个位的副本

运算

支持位运算!!!
就像一个普通的整数一样,可以进行与(&)、或(|)、异或(^)以及左移(<<)、右移(>>)运算。

成员函数表

注:二进制位从 0 开始,最右边一位是第 0 位。

Member functionsDefinition
any()判断是否存在置为 1 的二进制位
none()判断是否不存在置为 1 的二进制位
count()二进制位为 1 的个数
size()二进制位的个数
b[pos]访问 pos 处的二进制位
test(pos)判断在 pos 处的二进制位是否为 1
set()把所有二进制位都置为 1
set(pos)把在 pos 处的二进制位置为 1
set(pos, x)把在 pos 处的二进制位置为 x
reset()把所有二进制位都置为 0
reset(pos)把在 pos 处的二进制位置为 0
flip()把所有二进制位都取反
flip(pos)把在 pos 处的二进制位取反
to_ulong()用同样的二进制位返回一个 unsigned long 值
to_ullong()同上,只是返回一个 unsigned long long 值
to_string()返回一个 string 字符串
os << b把 b 的位集输出到 os 流

更多用法见 cplusplus.com

附:位运算技巧

注意:由于位运算优先级很低,所以要勤加括号。

判断两个数是否同号

!((x ^ y) >> 31)

交换两个数

a ^= b, b ^= a, a ^= b

求一个数 n 的绝对值

int 型右移 31 位取出符号
(n ^ (n >> 31)) - (n >> 31)

提取 lowbit

一个数 x 在二进制下最右边一个1开始至最低位的那部分是 lowbit(x)
应用:树状数组、遍历集合

  • lowbit(x) = x & (x ^ (x - 1))
  • lowbit(x) = x ^ (x & (x - 1))
  • lowbit(x) = x & -x

提取末尾(低位)连续的 1

对一个数 +1 时,其末尾连续的 1 会变成 0,末位的 0 会变成 1。
x & (x ^ (x + 1))