Bitset小记
简介
std::bitset
标准库中的一个存储0/1
的大小不可变容器。严格来讲,它并不属于 STL。
由于内存地址是按字节即byte
寻址,而非比特bit
,一个bool
类型的变量,虽然只能表示0/1
, 但是也占了1 byte
的内存。
bitset
就是通过固定的优化,使得一个字节的八个比特能分别储存 8 位的0/1
。
对于一个 4 字节的 int 变量,在只存0/1
的意义下,bitset
占用空间只是其,计算一些信息时,所需时间也是其。
在某些情况下通过bitset
可以优化程序的运行效率。至于其优化的是复杂度还是常数,要看计算复杂度的角度。一般bitset
的复杂度记为:(设原复杂度为)
- ,其中,这种记法较为普遍接受
- ,其中为计算机一个整型变量的大小
构造函数
用字符串构造时,字符串只能包含 ‘0’ 或 ‘1’ ,否则会抛出异常。
构造时,需在<>
中表明 bitset 的大小(即size)。
定义完bitset之后,可以用[]
访问元素,注意最低为下标为0,也可以通过这种方式对某一位元素赋值也是可以的。这里可以等价于数组
在进行有参构造时,若参数的二进制表示比bitset的size小,则在前面用0补充;若比bitsize大,参数为整数时取后面部分,参数为字符串时取前面部分
注意
bitset用字符串构造时,可以看作是用倒着写的二进制数字进行构造
1
2
3
4
5 bitset<4> foo ("1011");
cout << foo[0] << endl; //1
cout << foo[1] << endl; //1
cout << foo[2] << endl; //0
再看下面的两个栗子:
1 | bitset<4> bitset1; //无参构造,长度为4,默认每一位为0 |
1 | bitset<2> bitset1(12); //12的二进制为1100(长度为4),但bitset1的size=2,只取后面部分,即00 |
1 | bitset<4> foo ("1011"); |
bitset的位运算
注意式子中有两个及以上bitset时,各bitset的长度相等才能进行运算,不然会报错
1 | bitset<4> foo (string("1001")); |
可用函数
1 | bitset<8> foo ("10011011"); |
小记
bitset的主要用途:将某些真或假的状态以bitset的形式存储,然后在状态转移时,可以相较于普通的循环降低较大常数的复杂度(通常为64或者32)
- 例题
「LibreOJ β Round #2」贪心只能过样例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using namespace std;
bitset<1000005> ans[101];
int main()
{
int n, l, r;
scanf("%d", &n);
ans[0] = 1;
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &l, &r);
for(int j = l; j <= r; j++)
{
ans[i] |= (ans[i-1] << (j*j)); //在前面的所有状态,每个数都+j*j,也就是所有1左移j*j的位置
}
}
printf("%d\n", ans[n].count());
return 0;
}