bitset与set的介绍与使用(c++)

bitset

简单介绍:

bitset是一个序列,比较容易实现十进制与二进制转换,需要注意它的索引是从后往前的。

定义与初始化

在用bitset时,需要加一个头文件

#include<bitset>

然后进行定义与初始化

std::bitset<6>a(10)
cout<<a<<endl;//001010

这是定义了一个六位的bitset,然后初始化为10,如果在转化为二进制时,位数少于定义的位数,则输出的结果会在前面补0

部分函数的使用

函数意义
b.any()b中是否存在置为1的二进制位
b.none()b中是置为1的二进制位的个数
b.size()b中二进制位的个数
b[8]访问b在位置8处的二进制位
b.test(6)b在位置6处的二进制位
b.set()把b中所有二进制位置为1
b.reset()把b中所有二进制位置为0
b.set(6)把b中位置6为1
b.reset(3)把b中位置3为0
b.flip()把b中所有二进制位逐位取反
b.flip(9)把b中位置处的二进制逐位取反
b.to_ulong()将二进制下的b转为十进制的数

to_ulong的作用
是二进制的数转换成是十进制的(无符号)长整型数

代码:

#include<bits/stdc++.h>
using namespace std;
#include<bitset>
int main()
{
	std::bitset<16>b(13),c;
	cout<<b<<endl;//0000000000001101
	
	//b中是否存在置为1的二进制位 
	cout<<b.any()<<endl;//1
	
	//b中是否不存在置为1的二进制位 
	cout<<b.none()<<endl;//0
	
	//b中是置为1的二进制位的个数 
	cout<<b.count()<<endl;//3
	
	//b中二进制位的个数
	cout<<b.size()<<endl;//16
	
	//访问b在某位置处的二进制位
	cout<<b[8]<<endl;//0
	
	//b在某位置处的二进制位
	cout<<b.test(6)<<endl;//0
	
	//把b中所有二进制位置为1 
	cout<<b.set()<<endl;//1111111111111111
	
	//把b中所有二进制位置为0 
	cout<<b.reset()<<endl;//0000000000000000
	
	//把b中某位置为1 
	cout<<b.set(6)<<endl;//0000000001000000
	
	//把b中所某位置为0 
	cout<<b.reset(3)<<endl;//0000000001000000
	
	//把b中所有二进制位逐位取反 
	cout<<b.flip()<<endl;  //1111111110111111
	
	//把b中某位置处的二进制逐位取反
	cout<<b.flip(9)<<endl; //1111110110111111
	
	//将二进制下的b转为十进制的数,to_ulong的作用
	//是二进制的数转换成是十进制的(无符号)长整型数
	cout<<b.to_ulong()<<endl;//64959 
	
	return 0;
	
}

位运算操作符

符号意义
&按位与两个数的二进制同时为1,结果才为1,否则为0
按位或两个数的二进制有一个为1,结果为1,没有1,则为0
^异或两个数的二进制位相同为0,不同为1
~逐位取反
<< / >>将数位向左移,低位补0 / 将数位向右移,高位补0
== 与!=判断是否相等

代码:

#include<bits/stdc++.h>
using namespace std;
#include<bitset>
int main()
{
	std::bitset<5> b1(19);
	std::bitset<5> b2(9);
	cout<<b1<<endl;//10011
	cout<<b2<<endl;//01001
	
	//&按位与, 两个数的二进制同时为1,结果才为1,否则为0
	std::bitset<5> b3=b1&b2;
	cout<<b3<<endl;//00001
	
	//|按位或, 两个数的二进制有一个为1,结果为1,没有1,则为0
	b3=b1|b2;
	cout<<b3<<endl;//11011
	
	//^异或, 两个数的二进制位相同为0,不同为1 
	b3=b1^b2;
	cout<<b3<<endl;//11010
	
	//~逐位取反 
	b3=~b2;
	cout<<b3<<endl;//10110
	
	//<<将数位向左移,低位补0 
	b3=b1<<1;
	cout<<b3<<endl;//00110
	//>>将数位向右移,高位补0 
	b3=b1>>1; 
	cout<<b3<<endl;//01001
	
	//可以用==与!=判断是否相等
	bool equal=(b1==b2);
	cout<<equal<<endl; //0
	equal=(b1!=b2);
	cout<<equal<<endl; //1
	
	return 0;
}

应用:

当在统计数目时,我们依次循环会超时的时候,我们可以考虑用bitset,还可以去重,是个不错的方法

例题:

简单瞎搞题
题目链接

题意描述:

一共有 n个数,第 i 个数是 x[i],x[i]可以取 [ l[i] , r[i] ] 中任意的一个值。
设 S=∑x[i]2,求 S 种类数。

解题思路:

1.用bitset来存储结果
2.每次的结果与前面的结果按位或,则可以在结果的位置0->1
3.如果在种类相同,则1会出现在同一位置,达到去重的目的

解题代码:

#include<bits/stdc++.h> 
using namespace std;
int n, m;
bitset<N> p,t;
int main()
{
    int n;
    cin>>n;
    p[0]=1;//初始为1,下面根据结果将1移位即可 
    for(int i=1;i<=n;i++)
    {
    	t.reset(); //将t所有位置 置为0 
    	int l,r;
    	cin>>l>>r;
    	for(int i=l;i<=r;i++)
    	t|=p<<(i*i); //每次根据结果将1移位在对应位置 
		p=t;//将t赋值给p	
	}//依次循环下来,出现的结果会在对应位置出现1 
	cout<<p.cout()<<endl;//统计1的个数即可 
    return 0;
}

set

简单介绍:

set是一个不含重复元素且按升序排列的容器

定义与使用:

与bitset类似,set也需要一个头文件

#include<set>

接下来是定义一个set容器:

set<int>a;//整型
set<double>b;//浮点型
set<char>c;//字符型
set<int>d[10];//代表10个set容器

函数的使用:

函数意义
a.insert(x)在set容器中插入元素x
a.find(x)在set容器中查找元素x
a.erase(a.find(x))在set容器中先找到元素x,再删除元素x
a.erase(x)在set容器中删除元素x
a.size()得到set容器中元素的个数
a.clear()清空容器中所有元素

注意:在遍历容器时,用迭代器遍历,并且set遍历时,不存在这种用法:

	set<int>::iterator s;
	for(s=a.begin();**s<=a.end()**;s++)
	{
		cout<<*s<<" ";
	}

当遍历输出时,应该用这种用法:

set<int>::iterator s;
	for(s=a.begin();**s!=a.end()**;s++)
	{
		cout<<*s<<" ";
	}

函数使用代码如下:

#include<bits/stdc++.h>
using namespace std;
#include<set>
int main()
{
	set<int>a;
	a.insert(3);
	a.insert(9);
	a.insert(3);
	a.insert(6);
	a.insert(9);
	a.insert(7);
	a.insert(8);
	a.insert(4);
	set<int>::iterator s;
	for(s=a.begin();s!=a.end();s++)
	{
		cout<<*s<<" ";
	}
    cout<<endl;//3 4 6 7 8 9
    
    //查找一个元素是否在set容器中
    int x=15,y=4;
	if(a.find(x)==a.end())
	cout<<"-1"<<endl;
	else
	cout<<x<<endl; //-1
	if(a.find(y)=zhu=a.end())
	cout<<"-1"<<endl;
	else
	cout<<y<<endl; //4
	
	//删除一个元素
	a.erase(a.find(4)); 
	for(s=a.begin();s!=a.end();s++)
	{
		cout<<*s<<" ";
	}
    cout<<endl;//3 6 7 8 9
    
    a.erase(7); 
	for(s=a.begin();s!=a.end();s++)
	{
		cout<<*s<<" ";
	}
    cout<<endl;//3 6 8 9
    
    //插入一些新元素
	a.insert(12);
	a.insert(19);
	a.insert(14);
	a.insert(17);
	a.insert(10);
	for(s=a.begin();s!=a.end();s++)
	{
		cout<<*s<<" ";
	}
    cout<<endl;//3 6 8 9 10 12 14 17 19
    
	//删除一个区间内的所有元素
 	a.erase(a.find(8),a.find(17));
	for(s=a.begin();s!=a.end();s++)
	{
		cout<<*s<<" ";
	}
    cout<<endl;//3 6 17 19
    
    //获取set内元素的个数
	cout<<a.size()<<endl; //4
	
	//清空set内的元素
	a.clear();
	cout<<a.size()<<endl; //0
	
	return 0;
	
}

set自定义排序:

set自动升序排列,我们可以像sort排序一样,写一个函数对set排序

代码如下:

#include<bits/stdc++.h>
using namespace std;
#include<set>
bool cmp(int x,int y)
{
	return x>y;
}
set<int,bool(*)(int,int)>a(cmp); 
int main()
{
	a.insert(4);
	a.insert(9);
	a.insert(28);
	a.insert(17);
	a.insert(8);
	for(set<int,bool(*)(int,int)>::iterator it=a.begin();it!=a.end();it++)
	cout<<*it<<" ";
	cout<<endl;//28 17 9 8 4
}
  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值