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
}