位运算

位运算,顾名思义,是对二进制数的一元或二元操作。位运算往往快于普通的加减乘除操作,可以节省很多时间。

位运算符

取反(NOT)

一元运算符,对二进制的每一位进行取反。使0变为1,1变为0

1
2
3

NOT 0111
= 1000

操作符用波浪线 ~表示

按位或(OR)

二元运算符,两个相应的二进制位中只要有一个为一,结果为1

1
2
3
4

0101
OR 0011
= 0111

操作符为 |

按位异或(XOR)

二元运算符,对每一位进行操作,相同为0,不同为1

1
2
3
4

0101
XOR 0011
= 0110

操作符 ^

按位与(AND)

二元运算符,只有位上的都为1,结果才为1,否则为0

1
2
3
4

0101
AND 0011
= 0001

操作符&

移位

左移<<右移>>
移位后高位丢弃,低位补0

1
2
3
4
5
6
7
8

0001
<< 3
= 1000

1010
>> 2
= 0010

位运算的技巧

  1. 去掉最后k位:x>>k
  2. 在最后加一个k个0:x<<k
  3. 在最后加一个1:(x<<1)+1
  4. 把最后一位变成1:x|1
  5. 取末k位:x&((1<<k)-1)
  6. 把末k位变成1:x|((1<<k)-1)
  7. 把右边的连续1变为0 x&(x+1)
  8. 2的n次方:1<<n
  9. 2n:n<<1
  10. n/2并向下取整:n>>1
  11. 取出n的第k位:(n>>k)&1
  12. 把整数n的第k位取反:n xor (1<<k)
  13. 使整数n的第k位赋值1:n|(1<<k)
  14. 使整数n的第k位赋值0:n&(~(1<<k))

    应用 快速幂

    求x^y模p的值,其中1<=a,b,p<=10^9
    1
    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;
    }