• 1.1 位运算


    1. 补码

    由于CPU在进行设计的时候只进行了加法器的设计,所以在它只会处理加法操作,那么问题来了如何进行减法操作呢?例如:A-B,我们可以将其看作是A+(-B)的形式。这样在计算机内部就会出现负数的形式,所以就引入了补码的概念,补码就是对数字进行按位取反再加一的操作,补码在计算机中进行储存负数。

    2. 移位运算

    1. 左移

    就是将二进制中的bit位向左移动一位,低位用0进行填充,高位越界后舍弃。

    2. 右移

    1. 算数右移

    就是将二进制中的bit位向右移动一位,高位用符号位进行填充,低位越界后舍弃。值得注意的一点-3>>1=-2, -3/2 = -1,算数右移按照向下取证的观点,除法运算按照向0取证的观点。

    2. 逻辑右移

    就是将二进制中的bit位向右移动一位,高位用0进行填充,低位越界后舍弃。

    3. 二进制状态压缩

    将一个长度为m的bool数组用二进制整数的每一bit位来表示并存储的方法。

    常用操作:

    1. 取出n的第k位bit的数值:n>>k & 1

    2. 取出n的0-k位的数值:n & ((1 << k) -1)

    3. 将n的第k位进行取反操作:n ^ (1 << k)

    4. 将n的第k位赋值成1:n | (1 << k)

    5. 将n的第k位赋值成0:n & (~(1<<k))

    4. 成对交换

    我们对n进行n^1的操作时发现,如果n为奇数这个操作可以转化成与他相邻的偶数,n ^ 1 ^ 1这样可以得到n本身,这样的数字交换称为成对交换。

    5. lowbit运算

    lowbit(n)表示非负数的最后一位1表示的数值是多少

    inline int lowbit(int n){
          return n & -n;
    }
    

       

     

     

    相关练习:

    1. 0101 a^b

    #include<iostream>
    
    using namespace std;
    
    
    int qmi(int a, int b, int p){
        int t = 1;
        while(b){
            if(b&1) t = 1ll * t * a % p;
            a = 1ll * a * a % p;
            b >>= 1;
    
        }
        
        return t % p;
    }
    
    
    int main(){
        int a,b,p;
        cin>>a>>b>>p;
        cout<<qmi(a,b,p)<<endl;
        return 0;
    }

    2. 0102 64位整数乘法

    #include<iostream>
    
    
    using namespace std;
    
    typedef long long LL;
    
    LL a, b, p;
    
    LL res(LL a, LL b, LL q){
        LL ret = 0, t = 1;
        while(b){
            if(b & 1) ret = (ret + a)  % q;
            b >>= 1;
            a = a * 2 % q; 
        }
        return ret % q;
    }
    
    int main(){
        cin>>a>>b>>p;
        
        cout<<res(a,b,p)<<endl;
        return 0;
    }

    3. POJ1995 Raising Modulo Numbers

    #include<iostream>
    
    using namespace std;
    
    int T, H, M;
    
    typedef long long LL;
    
    LL sum;
    
    
    void calc(int x, int y){
        
        LL t = 1;
        while(y){
            if(y & 1) t = (t * x) % M;
            x = 1ll * x * x % M;
            y >>= 1;
        }
        sum = (sum + t) % M;
        
    }
    
    int main(){
        cin>>T;
        while(T--){
            cin>>M>>H;
            sum = 0;
            for(int i = 0; i < H; ++i){
                int l, r;
                cin>>l>>r;
                calc(l, r);
            }
            cout<<sum <<endl;
        }
        
        
        return 0;
    }

    4. 0104 起床困难综合症

    #include<iostream>
    #include<cstdio>
    #include<map>
    using namespace std;
    
    
    typedef pair<string, int> PSI;
    const int N = 1e5+10, M = 1e9;
    
    PSI op[N];
    
    int n, m;
    
    
    
    
    int calc(int bit, int num){
        
        for(int i = 1; i <= n; ++i)
            if(op[i].first == "AND") num &= op[i].second >> bit;
            else if(op[i].first == "OR") num |= op[i].second >> bit;
            else num ^= op[i].second >> bit;
        return num & 1;
    }
    
    int main(){
    	#ifdef _DEBUG
    		freopen("input.txt", "r", stdin);
    		freopen("output.txt", "w", stdout);
    	#endif
        cin>>n>>m;
        for(int i = 1; i <= n; ++i)
            cin>>op[i].first>>op[i].second;
        
    
        int res = 0, ans = 0;
        for(int i = 29; ~i; --i){
            int l = calc(i, 0), r = calc(i, 1);
    		#ifdef _DEBUG
            cout<<i<<' ' << l << ' '<<r<<endl;
    		#endif
            if(res + (1 << i) <= m && l < r){
                ans += r << i;
                res += 1 << i;
            }
            else ans += l << i;
        }
        
        cout<<ans<<endl;
        return 0;
            
    }

    5. 0103 最短Hamilton路径

    #include<iostream>
    #include<cstring>
    
    using namespace std;
    
    const int N = 1 << 20, M = 20;
    
    int f[N][M], path[M][M];
    
    int n;
    
    
    int main(){
        cin>>n;
        for(int i = 0; i < n ;++i){
            for(int j = 0; j < n; ++j){
                cin>>path[i][j];
            }
        }
        
        
        memset(f, 0x3f, sizeof f);
        
        f[1][0] = 0;
        
        for(int i = 1; i < (1 << n); ++i){
            for(int j = 0; j < n; ++j){
                if(i & (1 << j)){
                    for(int k = 0; k < n; ++k){
                        if(((i - (1 << j)) & (1 << k))){
                            f[i][j] = min(f[i][j], f[i - (1<<j)][k]+path[k][j]);
                        }
                    }
                }
            }
        }
        
        
        cout<<f[(1<<n)-1][n-1]<<endl;
        return 0;
        
        
    }
    

      

     

     

     

     

     

  • 相关阅读:
    MonoRail学习Component
    Eclipse中用户库的使用
    ASP.Net2.0中自定义控件在page中的注册
    WF学习Console Workflow Application
    Which Style of Workflow When?[转]
    使用UserControl时,在Page中定义方式
    参数类型异常
    GridView使用一些记录
    在使用Mybatis进行测试时出现报错:Caused by: java.lang.ClassNotFoundException: Cannot find class: Student
    递归反向输出字符串
  • 原文地址:https://www.cnblogs.com/hebust-fengyu/p/11649087.html
Copyright © 2020-2023  润新知