恶心至极
位运算入门
整数的存储
short y=-25;
原码 就是这个数字原始的二进制形式,只不过最高位表示符号。 1000 0000 0001 1001 反码 :将原码除符号位外其余的按位取反 1111 1111 1110 0110 补码 :反码加
1
1
1 1111 1111 1110 0111 有符号类型使用补码表示法存储整数,正数和
0
0
0 用原码,负数用补码。 有符号类型的最左边的二进制位是符号位。
n
n
n 位有符号类型的表示范围是
[
−
2
n
−
1
,
2
n
−
1
−
1
]
[-2^{n-1},2^{n-1}-1]
[ − 2 n − 1 , 2 n − 1 − 1 ] ,可以看作是模
2
n
2^n
2 n 意义下的数。
位运算
与 &
&
的意思是与(都是
1
1
1 才取
1
1
1 )。
0
,
1
0,1
0 , 1 与
1
1
1 等于它本身,
0
,
1
0,1
0 , 1 与
0
0
0 等于
0
0
0 。
x
x
x 为奇数时,
x
&
1
=
1
x\&1=1
x & 1 = 1 ;
x
x
x 为偶数时,
x
&
1
=
0
x\&1=0
x & 1 = 0 。
或 |
|
的意思是或(只要有
1
1
1 就取
1
1
1 )。
0
,
1
0,1
0 , 1 或
1
1
1 等于
1
1
1 ,
0
,
1
0,1
0 , 1 与
0
0
0 等于它本身。
异或 ^
^
的意思是异或(同为0,异为1)。
0
,
1
0,1
0 , 1 异或
1
1
1 等于本身取反,
0
,
1
0,1
0 , 1 异或
0
0
0 等于它本身。
x
∧
1
x\land 1
x ∧ 1 将偶数的最后一位强制变为
1
1
1 ,也就是变为与它相邻的奇数;将奇数的最后一位强制变为
0
0
0 ,也就是变为与它相邻的偶数。
取反 ~
~
的意思是取反。
∼
x
=
−
x
−
1
\sim x=-x-1
∼ x = − x − 1
移位 << >>
x<<y
把
x
x
x 的每个二进制位向左移动
y
y
y 位,移动造成的最右边的空位由
0
0
0 补足,最左边的数溢出。 x>>y
把
x
x
x 的每个二进制位向右移动
y
y
y 位,移动造成的最左边的空位由
0
0
0 补足,最右边的数溢出。 有符号类型右移,最左边补符号位。
优先级
~
比乘、除、取模的优先级高。 <<
,>>
比比较运算优先级高,比加减优先级低。 &
,^
,|
优先级由高到低,比比较运算优先级低,比逻辑运算优先级高。 c++有四大类运算符:
单目运算符(-a,~a,!a,++a,--a,&a,*a;a++,a--,a.x,a->x,a(x),a::x
)
双目运算符(*,/,%;+,-;<<,>>;<,>,<=,>=;!=,==;&,^,|;&&,||
)
三目运算符
赋值运算符
四个大类的优先级由高到低。
综合应用
变换操作
针对
x
x
x 二进制的第
i
i
i 位(从第
0
0
0 位开始)
获取,得到
0
0
0 或
1
1
1 :
x
>
>
i
&
1
x>>i\&1
x > > i & 1
获取,得到
2
i
2^i
2 i :
x
&
1
<
<
i
x\&1<<i
x & 1 < < i
i
=
0
i=0
i = 0 时判断奇偶:
x
&
1
x\&1
x & 1
取反:
x
∧
1
<
<
i
x\land 1<<i
x ∧ 1 < < i
置为
1
1
1 :
x
∣
1
<
<
i
x|1<<i
x ∣ 1 < < i
置为
0
0
0 :
x
&
∼
(
1
<
<
i
)
x\&\sim(1<<i)
x & ∼ ( 1 < < i )
针对
x
x
x 二进制的前
i
i
i 位(不包括第
i
i
i 位)
获取:
x
&
(
1
<
<
i
)
−
1
x\&(1<<i)-1
x & ( 1 < < i ) − 1
取反:
x
∧
(
1
<
<
i
)
−
1
x\land(1<<i)-1
x ∧ ( 1 < < i ) − 1
置为
1
1
1 :
x
∣
(
1
<
<
i
)
−
1
x|(1<<i)-1
x ∣ ( 1 < < i ) − 1
置为
0
0
0 :
x
&
∼
(
(
1
<
<
i
)
−
1
)
x\&\sim((1<<i)-1)
x & ∼ ( ( 1 < < i ) − 1 )
把
x
x
x 二进制低位的连续的
0
0
0 都变成
1
1
1 :
x
∣
x
−
1
x|x-1
x ∣ x − 1 把
x
x
x 二进制低位的连续的
1
1
1 都变成
0
0
0 :
x
&
x
+
1
x\&x+1
x & x + 1
大小写转换
大写变小写,小写变大写:
c
h
∧
=
32
ch\land=32
c h ∧ = 3 2
全部变小写:
c
h
∣
=
32
ch|=32
c h ∣ = 3 2
全部变大写:
c
h
&
=
−
33
ch\&=-33
c h & = − 3 3
常用操作
代替乘除模
x
×
2
i
=
x
<
<
i
x
÷
2
i
=
x
>
>
i
x
m
o
d
  
2
i
=
x
&
(
1
<
<
i
)
−
1
x\times2^i=x<<i\\x\div2^i=x>>i\\x\mod2^i=x\&(1<<i)-1
x × 2 i = x < < i x ÷ 2 i = x > > i x m o d 2 i = x & ( 1 < < i ) − 1 其中除法无论正负都是向下取整,负数取模会得到非负的结果。
找右起第一个
1
1
1 :
l
o
w
b
i
t
(
x
)
=
x
&
−
x
lowbit(x)=x\&-x
l o w b i t ( x ) = x & − x
x
−
l
o
w
b
i
t
(
x
)
x-lowbit(x)
x − l o w b i t ( x ) 相当于把
x
x
x 的右起第一个
1
1
1 减掉
枚举除了空集以外的
S
S
S 的所有子集
T
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<<31
,0x80000000
long long
的上限:0ull>>1
,-1ull>>1
,0x7fffffffffffffff
long long
的下限:1ll<<63
,0x8000000000000000
加与异或(NKOJ 3672)
问题描述 给出两个整数
A
A
A 和
B
B
B ,求 一个解
x
,
y
x,y
x , y 使得
x
+
y
=
A
,
x
∧
y
=
B
x+y=A,x\land y=B
x + y = A , x ∧ y = B 若有多解求
x
x
x 最小的一个,题目保证有解! 输入格式 两个整数
A
A
A 和
B
B
B 。 输出格式 两个整数,分别表示
x
x
x 和
y
y
y 。 样例输入 142 76 样例输出 33 109 提示
0
⩽
A
,
B
⩽
100
,
000
,
000
,
000
,
000
0\leqslant A,B\leqslant 100,000,000,000,000
0 ⩽ A , B ⩽ 1 0 0 , 0 0 0 , 0 0 0 , 0 0 0 , 0 0 0
考虑把
x
+
y
x+y
x + y 用位运算表示。
x
+
y
=
x
∧
y
+
2
(
x
&
y
)
x+y=x\land y+2(x\&y)
x + y = x ∧ y + 2 ( x & y )
其中
x
∧
y
x\land y
x ∧ y 统计
x
,
y
x,y
x , y 的二进制位上一个为
0
0
0 、一个为
1
1
1 的位置的和(相加为
1
1
1 );
x
&
y
x\&y
x & y 统计
x
,
y
x,y
x , y 的二进制位上都为
1
1
1 的位置和,乘以
2
2
2 (相当于左移)表示进位。 转换后得到
x
&
y
=
x
+
y
−
x
∧
y
2
x\&y=\frac{x+y-x\land y}2
x & y = 2 x + y − x ∧ y
∵
y
⩽
x
&
y
\because y\leqslant x\&y
∵ y ⩽ x & y ,
∴
y
=
x
&
y
\therefore y=x\&y
∴ y = x & y 时,
x
x
x 最小,此时
{
x
=
A
−
B
>
>
1
y
=
A
+
B
>
>
1
\begin{cases}x=A-B>>1\\y=A+B>>1\end{cases}
{ x = A − B > > 1 y = A + B > > 1
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}
⎩ ⎪ ⎪ ⎪ ⎨ ⎪ ⎪ ⎪ ⎧ 0 ⊗ 0 = a 0 ⊗ 1 = b 1 ⊗ 0 = c 1 ⊗ 1 = d 其中
a
,
b
,
c
,
d
a,b,c,d
a , b , c , d 是
0
0
0 或者
1
1
1 。 任意一组
a
,
b
,
c
,
d
a,b,c,d
a , b , c , d 的值,能不能将表达式
x
⊗
y
x\otimes y
x ⊗ y 用
x
,
y
x,y
x , y 以及位运算组成的表达式来代替? 答案1:
x
⊗
y
=
(
∼
x
&
∼
y
&
a
)
∣
(
∼
x
&
y
&
b
)
∣
(
x
&
∼
y
&
c
)
∣
(
x
&
y
&
d
)
x\otimes y=(\sim x\&\sim y\& a)|(\sim x\& y\& b)|(x\&\sim y\& c)|(x\& y\& d)
x ⊗ y = ( ∼ x & ∼ y & a ) ∣ ( ∼ x & y & b ) ∣ ( x & ∼ y & c ) ∣ ( x & y & d ) 答案2:
x
⊗
y
=
(
x
∣
y
∣
a
)
&
(
x
∣
∼
y
∣
b
)
&
(
∼
x
∣
y
∣
c
)
&
(
∼
x
∣
∼
y
∣
d
)
x\otimes y=(x|y|a)\&(x|\sim y|b)\&(\sim x|y|c)\&(\sim x|\sim y|d)
x ⊗ y = ( x ∣ y ∣ a ) & ( x ∣ ∼ y ∣ b ) & ( ∼ x ∣ y ∣ c ) & ( ∼ x ∣ ∼ y ∣ d )
x
0
,
x
1
,
…
,
x
n
−
1
x_0,x_1,\dots,x_{n-1}
x 0 , x 1 , … , x n − 1 都是
01
01
0 1 变量,
f
(
x
0
,
x
1
,
…
,
x
n
−
1
)
f(x_0,x_1,\dots,x_{n-1})
f ( x 0 , x 1 , … , x n − 1 ) 是一个函数,函数的输出也是
0
0
0 或
1
1
1 ,对于任意的
n
n
n 和任意的函数
f
f
f ,都可以写出位运算表达式, 表达式中只包含某些位运算,那么称这些位运算具有完备性 。 ~
,&
,|
三种运算具有完备性。
x
∣
y
=
∼
(
∼
x
&
∼
y
)
⇒
x|y=\sim(\sim x\&\sim y)\Rightarrow
x ∣ y = ∼ ( ∼ x & ∼ y ) ⇒ ~
和&
两种运算具有完备性。
x
&
y
=
∼
(
∼
x
∣
∼
y
)
⇒
x\& y=\sim(\sim x|\sim y)\Rightarrow
x & y = ∼ ( ∼ x ∣ ∼ y ) ⇒ ~
和|
两种运算具有完备性。
与非 ↑
x
↑
y
=
∼
(
x
&
y
)
x\uparrow y=\sim(x\&y)
x ↑ y = ∼ ( 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\uparrow x\\ x\&y=\sim(x\uparrow y)=(x\uparrow y)\uparrow (x\uparrow y) \end{array}\right\}\Rightarrow
∼ x = ∼ ( x & x ) = x ↑ x x & y = ∼ ( x ↑ y ) = ( x ↑ y ) ↑ ( x ↑ y ) } ⇒ 与非运算具有完备性。
或非 ↓
x
↓
y
=
∼
(
x
∣
y
)
x\downarrow y=\sim(x|y)
x ↓ y = ∼ ( 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
∼ x = ∼ ( x ∣ x ) = x ↓ x x ∣ y = ∼ ( x ↓ y ) = ( x ↓ y ) ↓ ( x ↓ y ) } ⇒ 或非运算具有完备性。