位运算,顾名思义,是对二进制数的一元或二元操作。位运算往往快于普通的加减乘除操作,可以节省很多时间。
位运算符
取反(NOT)
一元运算符,对二进制的每一位进行取反。使0变为1,1变为01
2
3
NOT 0111
= 1000
操作符用波浪线 ~
表示
按位或(OR)
二元运算符,两个相应的二进制位中只要有一个为一,结果为11
2
3
4
0101
OR 0011
= 0111
操作符为 |
按位异或(XOR)
二元运算符,对每一位进行操作,相同为0,不同为11
2
3
4
0101
XOR 0011
= 0110
操作符 ^
按位与(AND)
二元运算符,只有位上的都为1,结果才为1,否则为01
2
3
4
0101
AND 0011
= 0001
操作符&
移位
左移<<
右移>>
移位后高位丢弃,低位补01
2
3
4
5
6
7
8
0001
<< 3
= 1000
1010
>> 2
= 0010
位运算的技巧
- 去掉最后k位:
x>>k
- 在最后加一个k个0:
x<<k
- 在最后加一个1:
(x<<1)+1
- 把最后一位变成1:
x|1
- 取末k位:
x&((1<<k)-1)
- 把末k位变成1:
x|((1<<k)-1)
- 把右边的连续1变为0
x&(x+1)
- 2的n次方:
1<<n
- 2n:
n<<1
- n/2并向下取整:
n>>1
- 取出n的第k位:
(n>>k)&1
- 把整数n的第k位取反:
n xor (1<<k)
- 使整数n的第k位赋值1:
n|(1<<k)
- 使整数n的第k位赋值0:
n&(~(1<<k))
应用 快速幂
求x^y模p的值,其中1<=a,b,p<=10^91
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <cstdio>
#define ll long long
using namespace std;
ll power(ll x,ll y,ll p){
ll ans=1%p;
for(;y;y>>=1){
if(y&1)ans=ans*x%p;
x=x*x%p;
}
return ans;
}
int main(){
ll x,y,p;
scanf("%lld%lld%lld",&x,&y,&p);
printf("%lld",power(x,y,p));
return 0;
}