Forever Young

「笔记」位运算学习笔记

神仙位运算......

attack学长讲的我一头雾水,但我装作能听懂的样子2333

在讲位运算之前,学长插播了一点小知识,如下

memset

#include<bits/stdc++.h>
using namespace std;
int a[9999];
const int maxn=9999;

int main() {
    memset(a,maxn,sizeof(a));
    cout<<a[1];
    return 0;
}

 你觉得这段代码会输出什么?9999吗?

那你就大错特错了,它会输出一个很大的数,如下

至于为什么......点击这里,总之记得不要这样赋值就好了,我们乖乖的填上0、-1或者0x7f、0x3f就行了(也不能赋值1)

#include<bits/stdc++.h>
using namespace std;
int a[9999];

int main() {
    memset(a,0x7f,sizeof(a));
    cout<<a[1];
    return 0;
}

那么要是我们要精确赋值怎么办,别着急,就需要下面的fill函数

fill

fill(a+1,a+1+9999,2333);

这个东西感觉和sort的用法有些类似,a+1表示起点,a+1+9999表示终点,2333是要赋的值

#include<bits/stdc++.h>
using namespace std;
int a[9999];

int main() {
    fill(a+1,a+1+9999,2333);
    for(int i=1;i<=99;i++){
        cout<<a[i]<<" ";
    }
    return 0;
}

这样输出的就是2333啦!如下

位运算

&  按位与 

如果两个相应的二进制位都为1,则该位的结果值为1,否则为0

|   按位或

两个相应的二进制位中只要有一个为1,该位的结果值为1

^  按位异或

若参加运算的两个二进制位值相同则为0,否则为1

1^0=1;  0^1=1;  1^1=0;  0^0=1;

~  取反

 ~是一元运算符,用来对一个二进制(注意是二进制)数按位取反,即0变1,1变0

<<左移

用来将一个数的各二进制位全部左移N位,右补0 

>>右移

将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数,高位补0、

一些小技巧

  • ~a得到的值为-a-1
  • a!=b 可写成 a^b
  • a!=-1 可写成 ~a
  • a*2 可写成 a<<1;
  • a/2可写成 a>>1;
  • 同理a*2可写成 a<<n,a/2n可写成a>>n;
  • swap(a,b)可写成a^=b;b^=a;a^=b;
  • 提取一个数的二进制形式中1的个数:
while (x>0) {
    if(x&1)ans++;
    x>>=1;
}

一些函数

  • __builtin_popcount(x) 统计二进制下1的个数
  • __builtin_ctz(x) 统计末尾0的个数
  • __builtin_clz(x) 统计前缀0的个数
  • __builtin_parity(x) 判断奇偶性
posted @ 2019-04-11 09:12  Loceaner  阅读(272)  评论(0编辑  收藏  举报