位运算

本文代码适用于c++

什么是位运算

计算机中整数以二进制的形式存储在内存中。位运算即直接对整数的二进制进行二进制特有的运算。

一些约定

对于n位二进制整数,最右边为第0位(最低位),最左边为n-1位(最高位)。

默认对进行位运算的两个二进制整数位数相同(对位数较小的补0)。

暂时不考虑负数的位运算。

常见位运算

记xi为x的第i位数码,yi为y的第i位数码,zi同理

1.按位与
z=x&y ;则zi=1 当且仅当 xi=yi=1;

2.按位或
z=x|y ;则zi=1 当且仅当 xi,yi中至少有一个为1

3.按位异或
z=x^y ;则zi=1 当且仅当xi,yi中恰有一个为1

4.按位取反
z=~x ; 则zi=1 当且仅当 xi=1

5.左移/右移
x<<i/x>>i :把x向左/右整体移动i位(低位去0高位补0)

(111>>2)=1;(111<<2)=11100;

左移右移可以用来进行2的幂次的计算,如
x<<i :x*2^i
x>>i : [x/(2^i)]
(当i>30时 1<<i要改写成1ull<<i)

位运算在集合运算

集合的表示

给定两个集合 X,Y; |X并Y|=32,a0 a1--a31;
我们考虑用二进制数表示X集合:
xi=1当且仅当ai在X中

集合的运算

不难看出,利用位运算我们可以得到:
X并Y=x|y;
x交Y=x&y;
x在y中的补集=(x&y)^y

STL位运算--bitset

在用二进制表示集合时候,我们发现即使是unsigned long long最多也不过128个元素。遇到集合更大的情况怎么办呢?

std::bitset<N>s;//声明位数为N的二进制串s

s.set(i, 0); //将s的第i位数码改为0
s.set(i, 1); //将s的第i位数码改为1
s.test(i);//返回si的数值
s.count();//返回s中1的数目
s.reset();//将s设为全0`

<< ,>>, &, |, ~,也可以对bitset运算

例题(luogu)
1.B3695https://www.luogu.com.cn/problem/B3695

using namespace std;
std::bitset<30005> ss[30005];
std::bitset<30005> temp;
int main()
{
	int n,m,q,tmp;
	int c[1000006];
	int x,y,o;
	cin>>n>>m>>q;

	for(int i=0;i<m;i++)
		temp.set(i,1);
	for(int i=1;i<=n;i++)
		{
		cin>>c[i];
		for(int j=0;j<c[i];j++)
		{
			cin>>tmp;
			ss[i].set(tmp-1,1);//若j在集合si中 si的第j-1位为1
		}
	}
	while(q--)
	{
		scanf("%d %d %d",&o,&x,&y);
		if(o==1)
		{
			ss[x]=((ss[x]<<y)&temp);
		}
		else if(o==2)
		{
			ss[x]=(ss[x]>>y);
		}
		else if(o==3)
			cout<<(ss[x]&ss[y]).count()<<endl;//交
		else if(o==4)
			cout<<(ss[x]|ss[y]).count()<<endl;//并
		else if(o==5)
			cout<<(((ss[x]&ss[y])^ss[x])|((ss[x]&ss[y])^ss[y])).count()<<endl;//ssx与ssy的对称差
	}
	return 0;
}
posted @ 2025-10-13 22:44  Ahui2667d  阅读(41)  评论(0)    收藏  举报