学习bitset和有关例题(为了更快的暴力)

bitset介绍

bitset 是一个放二进制 0.1的容器,可以进行一些二进制可以进行的操作比如说或、且左移、右移等等。与普通的二进制位上进行的操作是相同的,每个元素仅用1bit空间,所以在于bitset 可以声明非常大的二进制位而不是仅仅限制于64位这样小的范围,并且它又保留了位运算快的优势。

bitset用法

    bitset<4> bitset1;  //无参构造,长度为4,默认每一位为0

    bitset<8> bitset2(12);  //长度为8,二进制保存,前面用0补充

    string s = "100101";
    bitset<10> bitset3(s);  //长度为10,前面用0补充
    
    char s2[] = "10101";
    bitset<13> bitset4(s2);  //长度为13,前面用0补充

    cout << bitset1 << endl;  //0000
    cout << bitset2 << endl;  //00001100
    cout << bitset3 << endl;  //0000100101
    cout << bitset4 << endl;  //0000000010101

bitset常用函数

b.any() b中是否存在置为1的二进制位?
b.none() b中不存在置为1的二进制位吗?
b.count() b中置为1的二进制位的个数
b.size() b中二进制位数的个数
b[pos] 访问b中在pos处二进制位
b.test(pos) b中在pos处的二进制位置为1么?
b.set() 把b中所有二进制位都置为1
b.set(pos) 把b中在pos处的二进制位置为1
b.reset( ) 把b中所有二进制位都置为0
b.reset( pos ) 把b中在pos处的二进制位置置为0
b.flip( ) 把b中所有二进制位逐位取反
b.flip( pos ) 把b中在pos处的二进制位取反
b.to_ulong( ) 把b中同样的二进制位返回一个unsigned

 

bitset 主要用于状态压缩, bitset 可以用每一位 0 或者 1 来表示可达性,例如图上点与点的可达性, dp 时可达性
bitset 主要用于暴力枚举,如果 bitset 的长度是 n, 一次与运算的复杂度就是 n/32
bitset 主要用于合并集合,交并补运算显示不同的逻辑意义

例题

简单瞎搞题

题目描述

一共有 n个数,第 i 个数是 xi 

xi 可以取 [li , ri] 中任意的一个值。

设 S=∑xi2S = \sum{ {x_i}^2}S=∑xi​2,求 S 种类数。

输入描述:

第一行一个数 n。 
然后 n 行,每行两个数表示 li,ri。

输出描述:

输出一行一个数表示答案。

题解:设s[i]表示为是否可以做到和为1,若我们现在求出了所有数的和,现在有个数x,我们把x放进去,对于已经s[i]=1的,那么是不是可以做出x+i?那么对于原来数组所有值为1的下标为i,再把i+x赋值为1就好了,即把s这个数组所有值左移x位即可。对于每一次取值后的位移去或运算,满足所有的情况。

#include <bits/stdc++.h>
using namespace std;
bitset<1000003> s,p;

int n;
int main() {
    s[0]=1;
    scanf("%d",&n);
    while(n--) {
        int l,r; scanf("%d%d",&l,&r);
        p.reset();
        for(int i=l;i<=r;i++){
            p|=(s<<(i*i));
        }
        s=p;
    }
    cout<<(int)s.count()<<endl;
    
    return 0;
}

参考链接:https://blog.csdn.net/chaiwenjun000/article/details/71154235https://www.cnblogs.com/magisk/p/8809922.html

猜你喜欢

转载自blog.csdn.net/qq_44132777/article/details/106215329