【位运算】位运算入门

版权声明:来自达羌蒟蒻 https://blog.csdn.net/PHenning/article/details/89282007

恶心至极

位运算入门

整数的存储

short y=-25;

原码就是这个数字原始的二进制形式,只不过最高位表示符号。
1000 0000 0001 1001
反码:将原码除符号位外其余的按位取反
1111 1111 1110 0110
补码:反码加 1 1
1111 1111 1110 0111
有符号类型使用补码表示法存储整数,正数和 0 0 用原码,负数用补码。
有符号类型的最左边的二进制位是符号位。
n n 位有符号类型的表示范围是 [ 2 n 1 , 2 n 1 1 ] [-2^{n-1},2^{n-1}-1] ,可以看作是模 2 n 2^n 意义下的数。

位运算

与 &

&的意思是与(都是 1 1 才取 1 1 )。

  • 0 , 1 0,1 1 1 等于它本身, 0 , 1 0,1 0 0 等于 0 0
  • x x 为奇数时, x & 1 = 1 x\&1=1 x x 为偶数时, x & 1 = 0 x\&1=0

或 |

|的意思是或(只要有 1 1 就取 1 1 )。

  • 0 , 1 0,1 1 1 等于 1 1 0 , 1 0,1 0 0 等于它本身。

异或 ^

^的意思是异或(同为0,异为1)。

  • 0 , 1 0,1 异或 1 1 等于本身取反, 0 , 1 0,1 异或 0 0 等于它本身。
  • x 1 x\land 1 将偶数的最后一位强制变为 1 1 ,也就是变为与它相邻的奇数;将奇数的最后一位强制变为 0 0 ,也就是变为与它相邻的偶数。

取反 ~

~的意思是取反。
x = x 1 \sim x=-x-1

移位 << >>

x<<y x x 的每个二进制位向左移动 y y 位,移动造成的最右边的空位由 0 0 补足,最左边的数溢出。
x>>y x x 的每个二进制位向右移动 y y 位,移动造成的最左边的空位由 0 0 补足,最右边的数溢出。
有符号类型右移,最左边补符号位。

优先级

~比乘、除、取模的优先级高。
<<,>>比比较运算优先级高,比加减优先级低。
&,^,|优先级由高到低,比比较运算优先级低,比逻辑运算优先级高。
c++有四大类运算符:

  • 单目运算符(-a,~a,!a,++a,--a,&a,*a;a++,a--,a.x,a->x,a(x),a::x
  • 双目运算符(*,/,%;+,-;<<,>>;<,>,<=,>=;!=,==;&,^,|;&&,||
  • 三目运算符
  • 赋值运算符

四个大类的优先级由高到低。

综合应用

变换操作

针对 x x 二进制的第 i i 位(从第 0 0 位开始)

  • 获取,得到 0 0 1 1 x &gt; &gt; i &amp; 1 x&gt;&gt;i\&amp;1
  • 获取,得到 2 i 2^i x &amp; 1 &lt; &lt; i x\&amp;1&lt;&lt;i
  • i = 0 i=0 时判断奇偶: x &amp; 1 x\&amp;1
  • 取反: x 1 &lt; &lt; i x\land 1&lt;&lt;i
  • 置为 1 1 x 1 &lt; &lt; i x|1&lt;&lt;i
  • 置为 0 0 x &amp; ( 1 &lt; &lt; i ) x\&amp;\sim(1&lt;&lt;i)

针对 x x 二进制的前 i i 位(不包括第 i i 位)

  • 获取: x &amp; ( 1 &lt; &lt; i ) 1 x\&amp;(1&lt;&lt;i)-1
  • 取反: x ( 1 &lt; &lt; i ) 1 x\land(1&lt;&lt;i)-1
  • 置为 1 1 x ( 1 &lt; &lt; i ) 1 x|(1&lt;&lt;i)-1
  • 置为 0 0 x &amp; ( ( 1 &lt; &lt; i ) 1 ) x\&amp;\sim((1&lt;&lt;i)-1)

x x 二进制低位的连续的 0 0 都变成 1 1 x x 1 x|x-1
x x 二进制低位的连续的 1 1 都变成 0 0 x &amp; x + 1 x\&amp;x+1

大小写转换

  • 大写变小写,小写变大写: c h = 32 ch\land=32
  • 全部变小写: c h = 32 ch|=32
  • 全部变大写: c h &amp; = 33 ch\&amp;=-33

常用操作

  • 代替乘除模
    x × 2 i = x &lt; &lt; i x ÷ 2 i = x &gt; &gt; i x m o d &ThinSpace;&ThinSpace; 2 i = x &amp; ( 1 &lt; &lt; i ) 1 x\times2^i=x&lt;&lt;i\\x\div2^i=x&gt;&gt;i\\x\mod2^i=x\&amp;(1&lt;&lt;i)-1 其中除法无论正负都是向下取整,负数取模会得到非负的结果。
  • 找右起第一个 1 1 l o w b i t ( x ) = x &amp; x lowbit(x)=x\&amp;-x
    x l o w b i t ( x ) x-lowbit(x) 相当于把 x x 的右起第一个 1 1 减掉
  • 枚举除了空集以外的 S S 的所有子集 T T
int S;
for(int T=S;T;T=S&T-1);
  • 交换正整数
void swap1(int&a,int&b){a=a^b,b=a^b,a=a^b;}
void swap2(int&a,int&b){a=a+b,b=a-b,a=a-b;}
  • 构造常数
    unsigned int的上限:~0u,-1u,0xffffffff
    int的上限:~0u>>1,-1u>>1,0x7fffffff
    int的下限:1<<310x80000000
    long long的上限:0ull>>1,-1ull>>1,0x7fffffffffffffff
    long long的下限:1ll<<63,0x8000000000000000

加与异或(NKOJ 3672)

问题描述
给出两个整数 A A B B ,求 一个解 x , y x,y 使得
x + y = A , x y = B x+y=A,x\land y=B
若有多解求 x x 最小的一个,题目保证有解!

输入格式
两个整数 A A B B

输出格式
两个整数,分别表示 x x y y

样例输入
142 76

样例输出
33 109

提示
0 A , B 100 , 000 , 000 , 000 , 000 0\leqslant A,B\leqslant 100,000,000,000,000

考虑把 x + y x+y 用位运算表示。
x + y = x y + 2 ( x &amp; y ) x+y=x\land y+2(x\&amp;y)

其中 x y x\land y 统计 x , y x,y 的二进制位上一个为 0 0 、一个为 1 1 的位置的和(相加为 1 1 ); x &amp; y x\&amp;y 统计 x , y x,y 的二进制位上都为 1 1 的位置和,乘以 2 2 (相当于左移)表示进位。
转换后得到
x &amp; y = x + y x y 2 x\&amp;y=\frac{x+y-x\land y}2

y x &amp; y \because y\leqslant x\&amp;y y = x &amp; y \therefore y=x\&amp;y 时, x x 最小,此时 { x = A B &gt; &gt; 1 y = A + B &gt; &gt; 1 \begin{cases}x=A-B&gt;&gt;1\\y=A+B&gt;&gt;1\end{cases}

long long a,b;
int main(){
	read(&a,&b);
	write(a-b>>1," ",a+b>>1,"\n");
	return 0;
}

完备性

假设现在需要一种位运算 \otimes ,满足 { 0 0 = a 0 1 = b 1 0 = c 1 1 = d \begin{cases}0\otimes 0=a\\0\otimes 1=b\\1\otimes 0=c\\1\otimes 1=d\end{cases}
其中 a , b , c , d a,b,c,d 0 0 或者 1 1
任意一组 a , b , c , d a,b,c,d 的值,能不能将表达式 x y x\otimes y x , y x,y 以及位运算组成的表达式来代替?
答案1: x y = ( x &amp; y &amp; a ) ( x &amp; y &amp; b ) ( x &amp; y &amp; c ) ( x &amp; y &amp; d ) x\otimes y=(\sim x\&amp;\sim y\&amp; a)|(\sim x\&amp; y\&amp; b)|(x\&amp;\sim y\&amp; c)|(x\&amp; y\&amp; d)
答案2: x y = ( x y a ) &amp; ( x y b ) &amp; ( x y c ) &amp; ( x y d ) x\otimes y=(x|y|a)\&amp;(x|\sim y|b)\&amp;(\sim x|y|c)\&amp;(\sim x|\sim y|d)

x 0 , x 1 , , x n 1 x_0,x_1,\dots,x_{n-1} 都是 01 01 变量, f ( x 0 , x 1 , , x n 1 ) f(x_0,x_1,\dots,x_{n-1}) 是一个函数,函数的输出也是 0 0 1 1 ,对于任意的 n n 和任意的函数 f f ,都可以写出位运算表达式, 表达式中只包含某些位运算,那么称这些位运算具有完备性
~,&,|三种运算具有完备性。
x y = ( x &amp; y ) x|y=\sim(\sim x\&amp;\sim y)\Rightarrow ~&两种运算具有完备性。
x &amp; y = ( x y ) x\&amp; y=\sim(\sim x|\sim y)\Rightarrow ~|两种运算具有完备性。

与非 ↑

x y = ( x &amp; y ) x\uparrow y=\sim(x\&amp;y)
x = ( x &amp; x ) = x x x &amp; y = ( x y ) = ( x y ) ( x y ) } \left.\begin{array}{l} \sim x=\sim(x\&amp;x)=x\uparrow x\\ x\&amp;y=\sim(x\uparrow y)=(x\uparrow y)\uparrow (x\uparrow y) \end{array}\right\}\Rightarrow 与非运算具有完备性。

或非 ↓

x y = ( x y ) x\downarrow y=\sim(x|y)
x = ( x x ) = x x x y = ( x y ) = ( x y ) ( x y ) } \left.\begin{array}{l} \sim x=\sim (x|x)=x\downarrow x\\ x|y=\sim(x\downarrow y)=(x\downarrow y)\downarrow (x\downarrow y) \end{array}\right\}\Rightarrow 或非运算具有完备性。

猜你喜欢

转载自blog.csdn.net/PHenning/article/details/89282007
今日推荐