Bitset

基本功能

类似一个二进制的数字, b i t s i t bitsit bitsit只能存储 1 1 1或者 0 0 0 t r u e true true或者 f a l s e false false),比如下面这一条:
在这里插入图片描述

定义
bitset<长度>名字;

当没有写using namespace std时,需要在前面加上std::的前缀。

操作

count():返回true的数量。
size():返回的大小。
any():若存在某一位是 true 则返回 true,否则返回 false。
none():若所有位都是 false 则返回 true,否则返回 false。
all():若所有位都是 true 则返回 true,否则返回 false。
set():将整个 bitset 设置成 true。
set(位置,true/false)):将某一位设置成 true/false。
reset():将整个 bitset 设置成 false。
reset(位置):将某一位设置成 false。相当于set(位置, false)
flip():翻转每一位(相当于异或一个全是1的bitset)。
flip(pos):翻转某一位。
to_string():返回转换成的字符串表达。
to_ulong():返回转换成的 unsigned long 表达。
to_ullong():返回转换成的 unsigned long long 表达。

注意

b i t s e t bitset bitset只能和同类型的变量进行 & \& & ∣ | ! ! !的位运算。

例题1

Switches and Lamps
由于 n ≤ 2000 n\le2000 n2000,所以可以考虑直接暴力。
每次选一个开关不管,看最后能不能打开所有灯。

//https://vjudge.net/problem/CodeForces-985B
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
void putstr(string s){
	for(int i=0;i<s.size();i++)putchar(s[i]);
}
int n,m;
bitset<2005>a[N];
signed main(){
	ios::sync_with_stdio(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char x;
			cin>>x;
			if(x=='1')a[i].set(j,1);//初始化bitset
		}
	}
	for(int i=1;i<=n;i++){
		bitset<2005>t;
		for(int j=1;j<=n;j++){
			if(i==j)continue;
			t|=a[j];
		}
		if(t.count()==m){//判断是否所有灯都打开
			putstr("YES");
			return 0;
		}
	}
	putstr("NO");
}

例题2

AT_abc258_g [ABC258G] Triangle
特水的一道 G G G题。
思路:首先,先找到两个有边相连的点,这两个点连接的共同的点就是两点贡献的答案。

//https://vjudge.net/problem/AtCoder-abc258_g
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e3+5;
void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x<10){putchar(x+'0');return;}
	print(x/10);
	putchar(x%10+'0');
}
int n;
bitset<3005>a[N];
signed main(){
	ios::sync_with_stdio(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			char x;
			cin>>x;
			if(j<=i)continue;//防止重复计算
			if(x=='1')a[i].set(j,1);//初始化
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if(a[i][j]){//有边相连
				bitset<3005>x=a[i]&a[j];//两点贡献
				ans+=x.count();
			}
		}
	}
	print(ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值