浅析 c++ bitset 的用法

总述

C++的 \(bitset\) 位于 <bitset> 头文件中,这是一种类似于数组的数据结构,每个位置存储 \(0\ or\ 1\) ,并且每个元素仅用 \(1\ bit\) 的空间

如果换一种方式来想,\(bitset\) 就是一个封装了一堆奇奇怪怪操作并支持状态压缩的 \(bool\) 数组,而且支持基本的位运算

定义 or 声明

  1. bitset<4> bitset1;  //无参构造,长度为4,默认每一位为0
  2. bitset<8> bitset2(12);  //长度为8,二进制保存,前面用0补充
  3. /*用string对象初始化bitset*/
  4. string s = "100101";
  5. bitset<10> bitset3(s);  //长度为10,前面用0补充
  6. /*用char对象初始化bitset*/
  7. char s2[] = "10101";
  8. bitset<13> bitset4(s2);  //长度为13,前面用0补充
  9. bitset<2> bitset5(12) //12的二进制为1100(长度为4),但bitset1的size=2,只取后面部分,即00
  10. cout << bitset1 << endl; //0000
  11. cout << bitset2 << endl; //00001100
  12. cout << bitset3 << endl; //0000100101
  13. cout << bitset4 << endl; //0000000010101
  14. cout << bitset5 << endl; //00

需要注意的是:在用string去初始化的时候,string 中的字符只能为 \(0\ or\ 1\)

操作

1.运算

位操作符 的用法相同

  1. bitset<4> foo (string("1001"));
  2. bitset<4> bar (string("0011"));
  3. cout << (foo^=bar) << endl; // 1010 (foo对bar按位异或后赋值给foo)
  4. cout << (foo&=bar) << endl; // 0010 (按位与后赋值给foo)
  5. cout << (foo|=bar) << endl; // 0011 (按位或后赋值给foo)
  6. cout << (foo<<=2) << endl; // 1100 (左移2位,低位补0,有自身赋值)
  7. cout << (foo>>=1) << endl; // 0110 (右移1位,高位补0,有自身赋值)
  8. cout << (~bar) << endl; // 1100 (按位取反)
  9. cout << (bar<<1) << endl; // 0110 (左移,不赋值)
  10. cout << (bar>>1) << endl; // 0001 (右移,不赋值)
  11. cout << (foo==bar) << endl; // false (0110==0011为false)
  12. cout << (foo!=bar) << endl; // true (0110!=0011为true)
  13. cout << (foo&bar) << endl; // 0010 (按位与,不赋值)
  14. cout << (foo|bar) << endl; // 0111 (按位或,不赋值)
  15. cout << (foo^bar) << endl; // 0101 (按位异或,不赋值)

2.访问

可以通过访问数组下标的形式访问 \(bitset\) 中的元素,注意最低位下标为 \(0\)

同时,也可以通过这种方式进行单点修改

  1. bitset<4> foo ("1011");
  2. cout << foo[0] << endl; //1
  3. cout << foo[1] << endl; //1
  4. cout << foo[2] << endl; //0
  5. cout << foo[3] << endl; //1

3.一些函数的使用

  1. bitset<1000> s;
  2. s.count(); //返回s中1的个数
  3. s.any(); //当s全为0时,返回false;如果有任何一位为1,则返回true
  4. s.none(); //当s全为0时,返回true;如果有任何一位为1,则返回false
  5. s.set(); //将s中每一位都设置为1
  6. s.set(3,0); //将s中第3位的数值设置为0
  7. s.set(3); //将s中第3位的数值设置为1
  8. s.reset(); //将s中每一位都设置为0
  9. s.flip(); //对s中每一位都取反

需要注意的是 s.reset()s.flip() 也可以传参数,和 s.set 的用法大致相同

4.一些操作

对于一类题,有这样的书写方式

  1. s |= s << w[i]

这句代码实际上是将 \(s\) 左移了 \(w[\ i\ ]\) 位,并且与原来的 \(s\) 取并集

下面拿两道例题举举栗子

Luogu P2347 [NOIP1996 提高组] 砝码称重

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int w[10]={0,1,2,3,5,10,20},a[10];
  4. bitset<1010> s;
  5. int main(){
  6. for(int i=1;i<=6;i++)
  7. cin>>a[i];
  8. s[0]=1;
  9. for(int i=1;i<=6;i++)
  10. for(int j=0;j<a[i];j++)
  11. s|=s<<w[i];
  12. cout<<"Total="<<s.count()-1<<endl;
  13. return 0;
  14. }

Luogu P1441 砝码称重

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=2010;
  4. int a[50],n,m,ans;
  5. inline int read(){
  6. int f=1,x;
  7. char ch;
  8. while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
  9. x=ch-'0';
  10. while('0'<=(ch=getchar())&&ch<='9') (x*=10)+=ch-'0';
  11. return x*f;
  12. }
  13. inline int cal(unsigned int x){
  14. int ret=0;
  15. while(x!=0){
  16. if(x&1) ret++;
  17. x>>=1;
  18. }
  19. return ret;
  20. }
  21. int main(){
  22. n=read(),m=read();
  23. for(int i=0;i<n;i++)
  24. //scanf("%d",&a);
  25. a[i]=read();
  26. for(int i=0;i<(1<<n);i++){
  27. if(cal(i)==n-m){
  28. bitset<N> s;
  29. s[0]=1;
  30. for(int j=0;j<n;j++)
  31. if(i&(1<<j))
  32. s|=s<<a[j];
  33. ans=max(ans,(int)s.count());
  34. }
  35. }
  36. cout<<ans-1<<endl;
  37. return 0;
  38. }

这两个题在对可以称出的质量进行统计的时候使用了这个小技巧,就可以摆脱 \(dfs+dp\) 的复杂方式,从而转化为 \(bitset\) 的一道题目,大大优化了时间复杂度和空间复杂度

浅析 c++ bitset 的用法的更多相关文章

  1. STL中bitset的用法

    终于又来写博客了 == bitset存储的是二进数位,就和一个bool性数组差不多.用法上和数组的操作方式也差不多. 每位只占一个字节,大大优化了空间,可以通过数组形式访问. bitset定义 可以用 ...

  2. bitset简单用法

    bitset的创建: #include<bitset> bitset<32> ar; //默认全为0 bitset<32> ar(n); //n的二进制 bitse ...

  3. bitset基础用法+心得

    今天上午听AntiLeaf学长讲课,获悉了bitset这种神奇的操作,还是大喊一句:stl大法吼啊! bitset是用来进行一些状态储存的操作.类似于一个标记数组,又类似于状压里面的二进制. 它与状压 ...

  4. bitset常用用法&&简单题分析

    Preface bitset,还是一个比较好用的STL,可以给一些题目做到神奇的常数优化(\(O(\frac{原来的复杂度}{机器的位数(32位or64位)})\)) 关于一些具体的函数等内容可以参考 ...

  5. BitSet的用法

    1,BitSet类    大小可动态改变, 取值为true或false的位集合.用于表示一组布尔标志. 此类实现了一个按需增长的位向量.位 set 的每个组件都有一个 boolean 值.用非负的整数 ...

  6. 浅析Java中CountDownLatch用法

    http://www.cnblogs.com/yezhenhan/archive/2012/01/07/2315652.html

  7. 浅析ajax原理与用法

    1 ajax原理 Ajax(Asynchronous JavaScript and XML (异步的JavaScript和XML)),是一种快速创建 动态网页的技术,目的是显示动态局部刷新.通过XML ...

  8. 【Web学习笔记】浅析CGI概念及用法

    1. CGI是什么         CGI是Common Gateway Interface的简写,它提供了一种标准方法使得位于WebServer后端的web应用可以根据client的请求动态生成网页 ...

  9. 位运算 进制转化 STL中bitset用法

    2017-08-17 16:27:29 writer:pprp /* 题目名称:输入十进制以二进制显示 程序说明:同上 作者:pprp 备注:无 日期:2017/8/17 */ #include &l ...

随机推荐

  1. 加密模块hashlib+日志模块logging

    目录 1.hashlib 加密模块 1.hashlib模块基本使用 1.2 详细操作 ①md5加密模式 ②sha256复杂加密模式 ③加盐操作(普通加盐) ④加盐操作(动态加盐) 2.logging ...

  2. 关于git和SVN的介绍和区别

    主要对git,svn进行一个简单的介绍. 顺带,我会在后面把我整理的一整套CSS3,PHP,MYSQL的开发的笔记打包放到百度云,有需要可以直接去百度云下载,这样以后你们开发就可以直接翻笔记不用百度搜 ...

  3. 基于FMC接口的Kintex-7 XC7K325T PCIeX4 3U PXIe接口卡

    一.板卡概述 本板卡基于Xilinx公司的FPGAXC7K325T-2FFG900 芯片,pin_to_pin兼容FPGAXC7K410T-2FFG900 ,支持PCIeX8.64bit DDR3容量 ...

  4. 「BUAA OO Pre」Git生成多个ssh key并连接GitLab仓库

    「BUAA OO Pre」Git生成多个ssh key并连接GitLab仓库 Part 0 前言 写作背景 笔者在配置学校GitLab的ssh key时遇到一些问题,原因应为曾经配置过GitHub的s ...

  5. 暑假撸系统6- Thymeleaf ajax交互!

    本来用Thymeleaf也没想着深度使用ajax,就是用也是非常传统的ajax方式提交然后js控制修改下变量.闲来无事的时候看Thymeleaf的教程发现一哥们的实现方式,以及实现思路,堪称惊奇,先说 ...

  6. MySQL 利用frm文件和ibd文件恢复表结构和表数据

    文章目录 frm文件和ibd文件简介 frm文件恢复表结构 ibd文件恢复表数据 通过脚本利用ibd文件恢复数据 通过shell脚本导出mysql所有库的所有表的表结构 frm文件和ibd文件简介 在 ...

  7. 做PPT必备的大数据分析网站,好看又免费的报表工具

    小明以前是学技术,跳槽来到一家大公司,在这个公司里会经常开会,比如有月度报告.季度报告以及年度报告,在开会前小明了解到同事们都会制作精美的PPT来汇报工作计划和目标,看到同事们精美的PPT里各种好看的 ...

  8. 【C# IO 操作 】Span<T>类

    Span 原理探究 ref结构 ref struct是仅在堆栈上的值类型: 表现一个顺序结构的布局:(译注:可以理解为连续内存) 只能在堆栈上使用.即用作方法参数和局部变量: 不能是类或正常结构的静态 ...

  9. maven-mvnd安装使用

    目录 安装使用 官方介绍 使用注意 安装使用 下载 https://github.com/apache/maven-mvnd/releases/tag/0.7.1 ,mvnd-0.7.1-darwin ...

  10. idea maven: invalid class root

    maven导入依赖没有问题,但是项目lib的类飘红,实际导入的类中有一些没有,这是idea的问题,重启idea,发现需要重新导入项目,重新导入后问题解决. 原因:可能之前误删了项目中idea的一些文件 ...