1.补码表示: ~x=-1-x
2.自然溢出:unsigned long long 自动对2^32取模,可以用来hash。
3.基本位运算操作:
左移:1<<n=2^n
n<<1=2n,n<<2=4n,n<<3=8n。。。
算术右移:n>>1=n/2 ,n>>4=n/16。。。算术右移=除以2向下取整 e.g. (-3) >> 1 = -2,3>>1=1
P.S. 整数/2 = 除以2向0取整 e.g. (-3)/2=-1 , 3/2=1
tips:以下二进制以0为最低位,即k从0开始。
取出整数n在二进制下的第k位:(n>>k)&1
取出整数n在二进制下的第0~k-1位(后k位):n&((1<<k)-1)
把整数n在二进制表示下的第k位取反:n^(1<<k)
把整数n在二进制表示下的第k位赋值为1:n|(1<<k)
把整数n在二进制表示下的第k位赋值为0:n&(~(1<<k))
以上常用于把一个n维bool数组压缩成一个n维二进制整数,即状态压缩,常用于状压DP。
注意符号的运算优先级:加减(+ -)>移位(>> <<)>比较大小(> < == !=)>位与(&)>异或(^)>位或(|)
可以直接每个运算符都加一个括号来提高正确性。
成对变换:n为偶数 n^1=n+1 ; n为奇数 n^1=n-1 so“0 1”,“2 3”构成成对变换,常用于存图中的边与其反向边。
lowbit: lowbit(x)=x&-x 返回x在二进制表示下的最低位的1及其后面的0构成的数值。是树状数组的核心。
4.快速幂 O(logn)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int main(){ ll a,b,p; scanf("%lld%lld%lld",&a,&b,&p); ll mul=1; for(;b;b>>=1){ if(b&1) mul=(mul*a)%p; a=(a*a)%p; } printf("%lld",mul%p); return 0; }
5.64位整数乘法 O(logn)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int main(){ ll a,b,p; scanf("%lld%lld%lld",&a,&b,&p); ll mul=0; for(;b;b>>=1){ if(b&1) mul=(mul+a)%p; a=(a*2)%p; } printf("%lld",mul%p); return 0; }
原文:https://www.cnblogs.com/Loi-Brilliant/p/9417598.html