浅析 c++ bitset 的用法
浅析 c++ bitset 的用法
总述
C++的 \(bitset\) 位于 <bitset> 头文件中,这是一种类似于数组的数据结构,每个位置存储 \(0\ or\ 1\) ,并且每个元素仅用 \(1\ bit\) 的空间
如果换一种方式来想,\(bitset\) 就是一个封装了一堆奇奇怪怪操作并支持状态压缩的 \(bool\) 数组,而且支持基本的位运算
定义 or 声明
bitset<4> bitset1; //无参构造,长度为4,默认每一位为0
bitset<8> bitset2(12); //长度为8,二进制保存,前面用0补充
/*用string对象初始化bitset*/
string s = "100101";
bitset<10> bitset3(s); //长度为10,前面用0补充
/*用char对象初始化bitset*/
char s2[] = "10101";
bitset<13> bitset4(s2); //长度为13,前面用0补充
bitset<2> bitset5(12) //12的二进制为1100(长度为4),但bitset1的size=2,只取后面部分,即00
cout << bitset1 << endl; //0000
cout << bitset2 << endl; //00001100
cout << bitset3 << endl; //0000100101
cout << bitset4 << endl; //0000000010101
cout << bitset5 << endl; //00
需要注意的是:在用string去初始化的时候,string 中的字符只能为 \(0\ or\ 1\)
操作
1.运算
与 位操作符 的用法相同
bitset<4> foo (string("1001"));
bitset<4> bar (string("0011"));
cout << (foo^=bar) << endl; // 1010 (foo对bar按位异或后赋值给foo)
cout << (foo&=bar) << endl; // 0010 (按位与后赋值给foo)
cout << (foo|=bar) << endl; // 0011 (按位或后赋值给foo)
cout << (foo<<=2) << endl; // 1100 (左移2位,低位补0,有自身赋值)
cout << (foo>>=1) << endl; // 0110 (右移1位,高位补0,有自身赋值)
cout << (~bar) << endl; // 1100 (按位取反)
cout << (bar<<1) << endl; // 0110 (左移,不赋值)
cout << (bar>>1) << endl; // 0001 (右移,不赋值)
cout << (foo==bar) << endl; // false (0110==0011为false)
cout << (foo!=bar) << endl; // true (0110!=0011为true)
cout << (foo&bar) << endl; // 0010 (按位与,不赋值)
cout << (foo|bar) << endl; // 0111 (按位或,不赋值)
cout << (foo^bar) << endl; // 0101 (按位异或,不赋值)
2.访问
可以通过访问数组下标的形式访问 \(bitset\) 中的元素,注意最低位下标为 \(0\)
同时,也可以通过这种方式进行单点修改
bitset<4> foo ("1011");
cout << foo[0] << endl; //1
cout << foo[1] << endl; //1
cout << foo[2] << endl; //0
cout << foo[3] << endl; //1
3.一些函数的使用
bitset<1000> s;
s.count(); //返回s中1的个数
s.any(); //当s全为0时,返回false;如果有任何一位为1,则返回true
s.none(); //当s全为0时,返回true;如果有任何一位为1,则返回false
s.set(); //将s中每一位都设置为1
s.set(3,0); //将s中第3位的数值设置为0
s.set(3); //将s中第3位的数值设置为1
s.reset(); //将s中每一位都设置为0
s.flip(); //对s中每一位都取反
需要注意的是 s.reset() 和 s.flip() 也可以传参数,和 s.set 的用法大致相同
4.一些操作
对于一类题,有这样的书写方式
s |= s << w[i]
这句代码实际上是将 \(s\) 左移了 \(w[\ i\ ]\) 位,并且与原来的 \(s\) 取并集
下面拿两道例题举举栗子
Luogu P2347 [NOIP1996 提高组] 砝码称重
#include <bits/stdc++.h>
using namespace std;
int w[10]={0,1,2,3,5,10,20},a[10];
bitset<1010> s;
int main(){
for(int i=1;i<=6;i++)
cin>>a[i];
s[0]=1;
for(int i=1;i<=6;i++)
for(int j=0;j<a[i];j++)
s|=s<<w[i];
cout<<"Total="<<s.count()-1<<endl;
return 0;
}
Luogu P1441 砝码称重
#include <bits/stdc++.h>
using namespace std;
const int N=2010;
int a[50],n,m,ans;
inline int read(){
int f=1,x;
char ch;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
x=ch-'0';
while('0'<=(ch=getchar())&&ch<='9') (x*=10)+=ch-'0';
return x*f;
}
inline int cal(unsigned int x){
int ret=0;
while(x!=0){
if(x&1) ret++;
x>>=1;
}
return ret;
}
int main(){
n=read(),m=read();
for(int i=0;i<n;i++)
//scanf("%d",&a);
a[i]=read();
for(int i=0;i<(1<<n);i++){
if(cal(i)==n-m){
bitset<N> s;
s[0]=1;
for(int j=0;j<n;j++)
if(i&(1<<j))
s|=s<<a[j];
ans=max(ans,(int)s.count());
}
}
cout<<ans-1<<endl;
return 0;
}
这两个题在对可以称出的质量进行统计的时候使用了这个小技巧,就可以摆脱 \(dfs+dp\) 的复杂方式,从而转化为 \(bitset\) 的一道题目,大大优化了时间复杂度和空间复杂度

浅析 c++ bitset 的用法的更多相关文章
- STL中bitset的用法
终于又来写博客了 == bitset存储的是二进数位,就和一个bool性数组差不多.用法上和数组的操作方式也差不多. 每位只占一个字节,大大优化了空间,可以通过数组形式访问. bitset定义 可以用 ...
- bitset简单用法
bitset的创建: #include<bitset> bitset<32> ar; //默认全为0 bitset<32> ar(n); //n的二进制 bitse ...
- bitset基础用法+心得
今天上午听AntiLeaf学长讲课,获悉了bitset这种神奇的操作,还是大喊一句:stl大法吼啊! bitset是用来进行一些状态储存的操作.类似于一个标记数组,又类似于状压里面的二进制. 它与状压 ...
- bitset常用用法&&简单题分析
Preface bitset,还是一个比较好用的STL,可以给一些题目做到神奇的常数优化(\(O(\frac{原来的复杂度}{机器的位数(32位or64位)})\)) 关于一些具体的函数等内容可以参考 ...
- BitSet的用法
1,BitSet类 大小可动态改变, 取值为true或false的位集合.用于表示一组布尔标志. 此类实现了一个按需增长的位向量.位 set 的每个组件都有一个 boolean 值.用非负的整数 ...
- 浅析Java中CountDownLatch用法
http://www.cnblogs.com/yezhenhan/archive/2012/01/07/2315652.html
- 浅析ajax原理与用法
1 ajax原理 Ajax(Asynchronous JavaScript and XML (异步的JavaScript和XML)),是一种快速创建 动态网页的技术,目的是显示动态局部刷新.通过XML ...
- 【Web学习笔记】浅析CGI概念及用法
1. CGI是什么 CGI是Common Gateway Interface的简写,它提供了一种标准方法使得位于WebServer后端的web应用可以根据client的请求动态生成网页 ...
- 位运算 进制转化 STL中bitset用法
2017-08-17 16:27:29 writer:pprp /* 题目名称:输入十进制以二进制显示 程序说明:同上 作者:pprp 备注:无 日期:2017/8/17 */ #include &l ...
随机推荐
- 针对某p社游戏某整合包的研究
软件分析 垃圾re手 最近在玩群星 创意工坊里面下载了整合包 进群下载排序文件后竟然发现要付费() 28R够吃一顿好的 马上来分析一下这个软件 这是一个四版整合包的mod安装器 其中樱花远征和新星纪元 ...
- 基于GDAL库,读取.grd文件(以海洋地形数据为例)Java版
技术背景 海洋地形数据主要是通过美国全球地形起伏数据(GMT)获得,数据格式为grd(GSBG)二进制数据,打开软件通过是Surfer软件,surfer软件可进行数据的编辑处理,以及进一步的可视化表达 ...
- Solution -「LOCAL」舟游
\(\mathcal{Description}\) \(n\) 中卡牌,每种三张.对于一次 \(m\) 连抽,前 \(m-1\) 次抽到第 \(i\) 种的概率是 \(p_i\),第 \(m\) ...
- 5道面试题,拿捏String底层原理!
原创:微信公众号 码农参上,欢迎分享,转载请保留出处. String字符串是我们日常工作中常用的一个类,在面试中也是高频考点,这里Hydra精心总结了一波常见但也有点烧脑的String面试题,一共5道 ...
- linux可以这样玩 之 杂乱无章的随笔(不定期更新)
文章目录 快速重命名 vim的进化 vim高亮当前行 vim列编辑 vim块编辑 vim行编辑 vim 中替换内容 vim保留当前已经编辑的内容,切换到其他用户继续编辑 修改服务的进程限制 CentO ...
- c++ TextQuery程序
TextQuery程序 我写的第一个版本 返回的是map<size_t, string>这个数据量很大,效率低下. TextQuery.h #inlucde<vector> # ...
- 带分数--第四届蓝桥杯省赛C++B/C组
第四届蓝桥杯省赛C++B/C组----带分数 思路: 1.先枚举全排列 2.枚举位数 3.判断是否满足要求 这道题也就是n=a+b/c,求出符合要求的abc的方案数.进行优化时,可以对等式进行改写,改 ...
- Dubbo源码剖析五之服务本地缓存
Dubbo调用者需要通过注册中心(例如:ZK)注册信息,获取提供者.但是如果频繁从ZK获取信息肯定会存在单点故障问题,所以Dubbo提供了将提供者信息缓存在本地的方法. Dubbo在订阅注册中心的回调 ...
- IDEA使用JDBC链接MySql(java编程)
1.在Maven的pom.xml文件中引入MySql的驱动 <dependency> <groupId>mysql</groupId> <artifactId ...
- kali linux 出现 E: 您在 /var/cache/apt/archives/ 上没有足够的可用空间。
问题: E: 您在 /var/cache/apt/archives/ 上没有足够的可用空间. 软链接到HOME下的一个目录即可,home下新建debs文件夹: 在某个空间大的分区建立一个目录,然后把/ ...