二进制与bitset

一.基础位运算(以代码中的符号为准)

运算符

与(&)(and):1&1=1 0&1=0 1&0=0 0&0=0
或(|)(or):1|1=1 0|1=1 1|0=1 0|0=0
异或(^)(xor):1^1=0 0^1=1 1^0=1 0^0=0
非(!)(not): !1=0 !0=1

逻辑移位

逻辑左移
x<<y 把x的每个二进制位向左移动y位,移动造成的最右边空位由0补足,最左边的数溢出。
逻辑右移
x>>y 把x的每个二进制位向右移动y位,移动造成的最左边空位由0补足,最右边的数溢出。
eg:1<<1=2,2>>1=1,3>>1=1,5<<2=20
所以,对于x,y,左移等于x乘上2^y(x<<y),右移相当于x除上2^y并向下取整(x>>y).

运算优先级

这里写图片描述
对于这种东西,记住很难,所以,多打括号吧!,借用学长的一句话:“多加几个括号累不死你,但是少加几个括号有可能会哭死在大街上。”

下面来说两道例题

1.给你n个数,其中有且仅有一个数出现了奇数次,其余的数出现了偶数次,让你输出这个出现了奇数次的数。这题卡空间,同时只能存两个数。

2.给你n个数,其中有且仅有两个数出现了奇数次,其余的数出现了偶数次,让你输出这两个出现了奇数次的数。

对于第一道题,根据xor的性质,我们可知一个数xor他自己等于0,所以初始ans=0,在读入后不断将其与ans xor,最后的ans即为答案。

对于第二道题,我们可以按照第一题的思路,将其xor,然后可得到一段二进制码,因为这两个数不相等,所以异或后的值(k)不为0。我们随便找出来k二进制表示下为1的一位。按照这位是0/1 分成两类,对每一类分别使用上一题的算法。

进入正题——bitset

什么是bitset

通俗来说就是一串只能表示01的数组(类似于二进制)。对于访问,和vector的元素一样,bitset中的位是没有命名的,我们只能按位置来访问它们。

头文件声明
#include<bitset>
using namespace std;
声明
bitset<n>a
/*建立一个长度为n的01数组。
注意,n为确定值,且初始时每一位都是0。
初始位置是0,也就是说,a[5]是非法访问。*/
常用函数
b[x]             //访问b中在x处的二进制位
b.count()        //b中置为1的二进制位的个数
b.size()         //b中二进制位的个数
b.set()          //把b中所有二进制位都置为1
b.set(x)         //把b中在x处的二进制位置为1
b.reset()        //把b中所有二进制位都置为0
b.reset(x)       //把b中在x处的二进制位置为0
b.flip()         //把b中所有二进制位逐位取反
b.flip(x)        //把b中在x处的二进制位取反

这就是bitset的常用函数,对于不常用和稀奇古怪的函数,可以访问cpulspuls进行查询。
一道例题
NOI2014起床困难综合症
题解

猜你喜欢

转载自blog.csdn.net/sjzezwzy/article/details/81089839