位运算的另一种姿势

在蒟蒻Cydiater日常水题的过程中,忽然遇到了一道题。中间有一个过程是要求在很快的时间内求出$1500$大小的两个01串的与之后存在多少个1。

最坏的,扫一遍,整体复杂度$O(N)$,好像没有什么可以优化的空间了QAQ。我开始考虑用位运算的与操作优化,因为其有$1500$个元素,所以可以考虑把这个东西拆成$\frac{N}{32}$个01串。

但是这之后好像就又存在一个问题。如何快速的统计一个二进制的01串里有多少个1?如果不要求$O(1)$,可以不停的统计lowbit,那么这个复杂度就和有多少个答案有关,这样的话最坏复杂度仍然是$O(N)$.

然后就去百度各种翻,看到了一个关于bitset的名词。然后xjb搞了搞后觉得很神奇,就先记下来。

BITSET

bitset是STL里的一种容器,也就是一个优化过的bool数组。里面存的就是一大串的01。

之所以说它优化过,是因为他不仅可以像int和long long一样进行与,或,异或操作。时间复杂度也大差不差。而且自带的一些函数也很方便使用,其中就包括了快速的统计出来一个bitset里有多少个1。

bitset的具体操作有很多,我列举几个比较常用的。

具体的定义如下:

#include <bitset>
using namespace std;
#define LENGTH 32
#define bs bitset<LENGTH>
bs S;

这里面的LENGTH就是要定义的长度,也就是里面具体有几个01元素。

因为他重载了[],所有可以像访问数组一样访问任意位。

复制一段别人的代码:

#include <iostream>
#include <bitset>
using namespace std;  

int main(){
    //bitset 使用整数初始化bitset
    bitset<3> bs(7);
    //输出bs各个位的值
    cout<<"bs[0] is "<<bs[0]<<endl;
    cout<<"bs[1] is "<<bs[1]<<endl;
    cout<<"bs[2] is "<<bs[2]<<endl;
    //下面的语句会抛出outofindexexception
    //cout<<"bs[3] is "<<bs[3]<<endl;  

    //使用字符串初始化bitset
    //注意:使用string初始化时从右向左处理,如下初始化的各个位的值将是110,而非011
    string strVal("011");
    bitset<3> bs1(strVal);
    //输出各位
    cout<<"bs1[0] is "<<bs1[0]<<endl;
    cout<<"bs1[1] is "<<bs1[1]<<endl;
    cout<<"bs1[2] is "<<bs1[2]<<endl;
    //cout输出时也是从右边向左边输出
    cout<<bs1<<endl;  

    //bitset的方法
    //any()方法如果有一位为1,则返回1
    cout<<"bs1.any() = "<<bs1.any()<<endl;  

    //none()方法,如果有一个为1none则返回0,如果全为0则返回1
    bitset<3> bsNone;
    cout<<"bsNone.none() = " <<bsNone.none()<<endl;  

    //count()返回几个位为1
    cout<<"bs1.count() = "<<bs1.count()<<endl;  

    //size()返回位数
    cout<<"bs1.size() = "<<bs1.size()<<endl;  

    //test()返回某一位是否为1
    //flip()诸位取反
    bitset<3> bsFlip = bs1.flip();
    cout<<"bsFlip = "<<bsFlip<<endl;  

    //to_ulong
    unsigned long val = bs1.to_ulong();
    cout<<val;
}
时间: 2024-11-04 14:22:38

位运算的另一种姿势的相关文章

位运算和关于两个数交换的多种方法

我们知道,位运算在计算中有着广泛的应用. 在计算机的各种编程语言中位运算也是一种不可缺少的运算,尤其是在计算机的底层实现代码中. 以下我们就来介绍一下位运算. 1.左移运算<<  左移右移都是移动二进制数 0000-0000 0000-0000 0000-0000 0000-1100     =12 向左移动一位变为(右边缺几位就补几个0) 0000-0000 0000-0000 0000-0000 0001 1000       =24 再向左移一位 0000-0000 0000-0000

位运算的使用和一些技巧

位运算有以下几种:- & ^ |,为 按位取反 按位与 按位异或 按位或,优先级从左到右依次降低. 按位与运算有两种典型用法,一是取一个位串信息的某几位,如以下代码截取x的最低7位:x & 0177.二是让某变量保留某几位,其余位置0,如以下代码让x只保留最低6位:x = x & 077. 按位或运算的典型用法是将一个位串信息的某几位置为1.如将要获得最右4位为1,其他位与变量j原来其他位保持相同,可用逻辑或运算017|j: 按位异或运算的典型用法是求一个位串信息的某几位信息的反.

Java中的二进制及基本的位运算

Java中的二进制及基本的位运算 二进制是计算技术中广泛采用的一种数制.二进制数据是用0和1两个数码来表示的数.它的基数为2,进位规则是"逢二进一",借位规则是"借一当二",由18世纪德国数理哲学大师莱布尼兹发现.当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的.计算机中的二进制则是一个非常微小的开关,用"开"来表示1,"关"来表示0. 那么Java中的二进制又是怎么样的呢?让我们一起来揭开它神

数据结构与算法-位运算

位运算位运算是把数字用二进制表示之后,对每一位上的0或者1的运算.理解位运算的第一步是理解二进制.二进制是指数字每一位都是0或者1,如十进制的2转换为二进制之后是10,而十进制的10转换为二进制之后是1010.在程序员圈子里有一个流传了很久的笑话,说世界上有10种人,一种人知道二进制,另一种人不知道二进制. 下面是几个常见的关于位运算的算法题:基本位运算位运算总共只有5种运算:与&,或|,异或^,左移<<,右移>>.与,或,异或的运算规则: 左移,右移运算规则:左移运算m

位运算之异或运算

位运算 位运算就是基于整数的二进制表示进行的运算.理解位运算首先要理解二进制.位运算总共只有5种运算:与(&).或(|).异或(^).左移(<<).右移(>>). 异或运算 维基百科中对「异或」的解释: 在逻辑学中,逻辑算符异或(exclusive or)是对两个运算元的一种逻辑析取类型,符号为 XOR 或 EOR 或 ⊕(编程语言中常用^).但与一般的逻辑或不同,异或算符的值为真仅当两个运算元中恰有一个的值为真,而另外一个的值为非真.转化为命题,就是:"两者的值

几种常见的位运算

1.判断奇偶数 如果把一个数n以二进制数的形式表示的话,我们只需要判断最后一个二进制位是1还是0即可.如果是1,则代表奇数,否则为偶数.代码如下: if(n & 1 == 1){ // n是奇数 } 2.交换两个数 x = x ^ y; // (1) y = x ^ y; // (2) x = x ^ y; // (3) 我们都知道两个相同的数异或之后的结果为0,即 n ^ n = 0,并且任何数与0异或之后等于它本身,即 n ^ 0 = n. 于是我们把(1)中的x代入(2)中的x,有:y =

poj 2799 IP Networks 模拟 位运算

poj链接:http://poj.org/problem?id=2799 这题实在是非常的有趣... 写的时候也非常的开心... 然后就写跪了... 刚好讲了ip地址和子网掩码的只是 整个学期的通信导论我就只有这节课有事没去结果昨晚把这方面的只是补起来了有种功德圆满的感觉 network address是前(32-n)随意 后n位全零 network mask是前(32-n)全一 后n位全零 其次是练习了各种移位操作 我发现移位操作是个非常好用的东西 因为它自填充0 所以对一个二进制数往右移8位

Java I/O : Bit Operation 位运算

Writer      :BYSocket(泥沙砖瓦浆木匠) 微         博:BYSocket 豆         瓣:BYSocket FaceBook:BYSocket Twitter    :BYSocket 泥瓦匠喜欢Java,文章总是扯扯Java. I/O 基础,就是二进制,也就是Bit. 一.Bit与二进制 什么是Bit(位)呢?位是CPU处理或者数据存储最小的单元.类似于很小很小的开关,一开一关,表示为1或者0.所以,这就是计算机处理任何数据的"细胞",要谨记.

POJ 1166 The Clocks 位运算与BFS

1.题意:有一组3*3的只有时针的挂钟阵列,每个时钟只有0,3,6,9三种状态:对时针阵列有9种操作,每种操作只对特点的几个时钟拨一次针,即将时针顺时针波动90度,现在试求从初试状态到阵列全部指向0的状态所需要的最小操作数的操作方案: 2.输入输出:输入给出阵列初始状态,0,1,2,3分别表示0,3,6,9:要求输出最快方案的操作序列: 3.分析:IOI 1994的考题,BFS是比较容易想到的方法之一,关键是如何简洁的表示和改变BFS过程中的阵列状态:这里使用位运算的方法:具体如下: 首先一共9