一、介绍
std::bitset 是标准库中的一个存储 0/1 的大小不可变容器。通俗讲,bitset 相当于一个二进制的数组,并且可以直接用01串赋值
1.1 复杂度
由于内存地址是按字节即 byte 寻址,而非比特 bit,一个 bool 类型的变量,虽然只能表示 0/1, 但是也占了 1 byte 的内存。bitset 就是通过固定的优化,使得一个字节的八个bit能分别储存 8 位的 0/1。对于一个 4 字节的 int 变量,在只存 0/1 的意义下,bitset 占用空间只是其 1/32;计算一些信息时,所需时间也是其 1/32。
在某些情况下通过== bitset 可以优化程序的运行效率==。至于其优化的是复杂度还是常数,要看计算复杂度的角度。一般 bitset 的复杂度为:(设原复杂度为O(n) )==O(n/32)==这种记法不太严谨(复杂度中不应出现常数),但体现了 bitset 能将所需时间优化至 1/32
二、基本操作
/*bitset*/
#include<bits/stdc++.h>
using namespace std;
int main(){
//构造函数:
//bitset<n> b;b有n位,每位都为0.参数n可以为一个表达式
bitset<5>b;
cout<<b<<endl;//00000
//bitset<n> b(unsigned long u);b有n位,并用u赋值;如果u超过n位,则顶端被截除;如果U不足n位,则在前端补0
bitset<5>b1(5);
cout<<b1<<endl;//00101
//bitset<n> b(string s);b是string对象s(01串)中含有的位串的副本
string s ( "10011" );
bitset<5> b2(s);
cout<<b2<<endl;//10011
//[]: 访问其特定的一位
cout<<b2[0]<<' '<<b2[2]<<endl;//1 0
//set(): 将整个 bitset 设置成 true
//set(pos, val = true): 将某一位设置成 true/false
b.set();
cout<<b<<endl;//11111
//count(): 返回 true (1)的数量
cout<<b.count()<<endl;//0
cout<<b1.count()<<endl;//2
//size(): 返回 bitset 的大小
cout<<b.size()<<endl;//5
//any(): 若存在某一位是 true 则返回 true,否则返回 false
if(b.any()) cout<<"存在某一位是1"<<endl;//存在某一位是1
else cout<<"全是0"<<endl;
//to_string(): 返回转换成的字符串表达
cout<<b.to_string()<<endl;//11111
//to_ulong(): 返回转换成的 unsigned long 表达 ;
//to_ullong():返回转换成的 unsigned long long 表达
cout<<b2.to_ulong()<<endl;//19
//_Find_first(): 返回 bitset 第一个 true 的下标,若没有 true 则返回 bitset 的大小
cout<<b2._Find_first()<<endl;//0
//_Find_next(pos): 返回 pos 后面(下标严格大于 pos 的位置)第一个 true 的下标,若 pos 后面没有 true 则返回 bitset 的大小
//运算符
cout<<(b>>1)<<endl;//01111 (右移,不赋值)
cout<<b<<endl;//11111
cout<<(b<<=2)<<endl;//11100(左移2位,低位补0,有自身赋值)
cout<<b<<endl;//11100
//b=11100 b1=00101
cout<<(b1^=b)<<endl;//11001(b1对b按位异或后赋值给b1)
cout<<b<<' '<<b1<<endl;//11100 11001
cout<<(b1&=b)<<endl;//11000(b1对b按位与后赋值给b1)
cout<<(b1|=b)<<endl;//11100(b1对b按位或后赋值给b1)
}
三、应用举例
「LibreOJ β Round #2」贪心只能过样例
/*简单 DP+bitset*/
#include<bits/stdc++.h>
using namespace std;
bitset<1000005>bb[105];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int n,a,b;
cin>>n;
bb[0]=1;
//cout<<bb[0]<<endl;
for(int i=1;i<=n;i++){
cin>>a>>b;
for(int j=a;j<=b;j++){
bb[i]|=bb[i-1]<<(j*j);//第i个数=第i-1个数+j*j,也就是所有1左移j*j的位置
}
}
cout<<bb[n].count();
}