位运算学习笔记
神仙位运算......
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*2n 可写成 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) 统计二进制下0的个数
- __builtin_ctz(x) 统计末尾0的个数
- __builtin_clz(x) 统计前缀0的个数
- __builtin_parity(x) 判断奇偶性