zoukankan      html  css  js  c++  java
  • 位运算

    位运算

    基本的算术位运算:

    异或

    and,&

    or,|

    not,~

    xor

    • 补码

    32位无符号整数unsigned int:

    直接把这32位编码C看作32位二进制数N。

    32位有符号整数int:

    以最高位为符号位,0表示非负数,1表示负数。

    对于最高位为0的每种编码C,直接看作32位二进制数S。

    n为非负数,n的符号位(即最高位)为0,原码、反码、补码相同。

    n为负数,n的符号位(即最高位)为1,反码为原码除最高位取反,补码为反码加一。

    • 移位运算

    左移

    1<<n=2nn<<1=2n

    右移

    n>>1=n/2

     

    【例题】a^b(快速幂)

    代码如下:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    int main(){
        int a,b,p;
        cin>>a>>b>>p;
        ll ans=1%p;
    
        for(;b;b>>=1){
            if(b&1)ans=(ll)ans*a%p;
            a=(ll)a*a%p;
        }
    
        cout<<ans;
        return 0;
    }

     

    【例题】64位整数乘法

    方法一:类似于快速幂的思想

    代码如下:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    int main(){
        ll a,b,p,ans;
        cin>>a>>b>>p;
    
        for(;b;b>>=1){
            if(b&1)ans=(ans+a)%p;
            a=(a+a)%p;
        }
    
        cout<<ans;
        return 0;
    }

     

    方法二:long double做法

    a*b mod p=a*b-(a*b/p)*p

     

    代码如下:

    #include<bits/stdc++.h>
    #define ll long long
    #define ld long double
    using namespace std;
    
    int main(){
        ll a,b,p,c,ans;
        cin>>a>>b>>p;
    
        a%=p;b%=p;
        c=(ld)a*b/p;
        ans=a*b-c*p;
    
        if(ans<0)ans+=p;
        else if(ans>=p)ans-=p;
    
        cout<<ans;
        return 0;
    }
    • 二进制状态压缩

    操作

    运算

    取出整数n在二进制表示下的第k位

    (n>>k)&1

    取出整数n在二进制表示下的第0~k-1位(后k位)

    n&((1<<k)-1)

    把整数n在二进制表示下的第k位取反

    n xor (1<<k)

    对整数n在二进制表示下的第k位赋值为1

    n|(1<<k)

    对整数n在二进制表示下的第k位赋值为0

    n&(~(1<<k))

    【例题】最短Hamilton路径(状态压缩DP)

    使用一个n位的二进制数:若其第i(0≤i<n)位为1,则表示第i个点已经被经过,反之未被经过。

    F[i,j](0≤i<2n,0≤j<n):“点被经过的状态”对应的二进制数为i,且目前处于点j时的最短路径。

    初始值:F[1,0]=0,F数组的其他值设为无穷大。

    答案:F[(1<<n)-1,n-1]

    状态转移方程:F[i,j]=min{F[i xor (1<<j),k]+weight(k,j)}

    0≤k<n并且((i>>j)&1)=1

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    
    int n;
    int f[1<<20][20];
    int w[20][20];
    
    int main(){
        cin>>n;
        memset(f,0x3f,sizeof f);
        f[1][0]=0;
    
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                cin>>w[i][j];
    
        for(int i=1;i<1<<n;i++)
            for(int j=0;j<n;j++)if(i>>j&1)
                for(int k=0;k<n;k++)if(i>>k&1)
                    f[i][j]=min(f[i][j],f[i^1<<j][k]+w[k][j]);
    
        cout<<f[(1<<n)-1][n-1];
        return 0;
    }

    运算符优先级从高到低的顺序:

    加减

    移位

    比较大小

    位与

    异或

    位或

    +,-

    <<,>>

    >,<,==,!=

    &

    xor

    |

    • 成对变换

    对于非负整数n:

    n为偶数时,n xor 1等于n+1

    n为奇数时,n xor 1等于n-1

    “0与1”、“2与3”、“4与5”……关于xor 1运算构成“成对变换”。

    • lowbit运算

    lowbit(n)取出非负整数n在二进制表示下最低位的1以及它后边的0构成的数值。

    lowbit(n)=n&(~n+1)=n&(-n)

     

    作用: 

    ①配合Hash可以找出整数二进制表示下所有是1的位,所花费的时间与1的个数统计。

    ②是树状数组中的一个基本运算。

    const MAX_N=1<<20
    int H[MAX_N+1];
    
    for(int i=0;i<=20;i++)H[1<<i]=i;
    while(cin>>n){
        while(n>0){
            cout<<H[n&-n]<<‘ ’;
            n=n&-n;
        }
    }

     

  • 相关阅读:
    淘宝客服务费和佣金的区别是什么
    java编程出现的错误对应的解决方法
    若遇到APP无法抓包怎么办,可以通过安装drony 进行转发抓包
    Android逆向—苏宁金融app的data参数分析
    GMSSL 支持SM2/SM3/SM4
    Frida安装和使用
    JS 解析 bytearray 成字符串
    Pytorch-tensor的创建,索引,切片
    深度学习实战之线性回归1
    CCF CSP 201803-2 碰撞的小球
  • 原文地址:https://www.cnblogs.com/zhengchang/p/weiyunsuan.html
Copyright © 2011-2022 走看看