zoukankan      html  css  js  c++  java
  • 位运算、快速幂

     位运算:

    快速幂: 

    例1. a^b%p

    题目链接:https://www.acwing.com/problem/content/91/

     

    #include<iostream>
    using namespace std;
    int main(){
        int a, b, p;
        cin>> a >> b >> p;
        int res = 1 % p;   //若b=0时,不会进入while循环,故res要先模p
        while(b){
            if(b&1)
            //若b的个位为1
                res = res * 1ll * a % p;  //1ll是将res转化为长整型
                a = a * 1ll * a % p;
                b >>= 1;
        }
        cout<<res<<endl;
        return 0;
    }

    例2.  a*b%p

    https://www.acwing.com/problem/content/92/

    两个10^18的数相乘是溢出的,但是相加是不溢出的。

     

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

    例3.旅行商问题

    https://www.acwing.com/problem/content/93/

    思路:

    假设四个点:0,1,2,3

    有两条路径:0 -> 1 -> 2 -> 3  (最短距离为18)

    和 0 -> 2 -> 1 -> 3   (20)

     

    两个关键要素:

    1)哪些点被用过;

    2)目前停在哪个点上。

    用 f[state][j] 来表示 state:当前哪个点被用过(是个集合);j:停在哪个点上。

    若从k点转移过来:f[state][j] = f[state_k][k] + weight[k][j],state_k 是 state 除掉 j 之后的集合,且 state_k 要包含 k。

    用位运算来表示state这个集合,即用一个二进制整数来表示state。(状态压缩:用0表示这个点不存在,1表示这个点存在)。这里1<=n<=20 所以用20位二进制来表示state。

    如:0, 1, 4 用二进制表示状态为:

    state = 10011

    索引: 43210

    注意:一般会将大数组定义为全局变量或静态变量(在堆空间),因为main()函数里C++默认是栈空间(默认为4M)。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N = 20, M = 1<<20;   //左移20, 相当于乘上2^20
    int n;
    int f[M][N], weight[N][N];
    int main(){
        cin>>n;
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
                cin>>weight[i][j];
        
        memset(f, 0x3f, sizeof(f));  //初始化f里的所有状态为正无穷
        f[1][0] = 0;   //最开始在0号点,故状态集合内只包含0号点, 还没有走过任何路程,故初始化为0
        
        for(int i=0; i<1<<n; i++){
            for(int j=0; j<n; j++){
                if(i>>j & 1){
                    //判断i的第j位是不是1:将i右移j位和1相与
                    for(int k=0; k<n; k++){
                        if(i-(1<<j) >>k & 1)
                            //把当前状态的第j位减去,再判断第k位是否为1,减法优先级比移位操作符高
                            f[i][j] = min(f[i][j], f[i-(1<<j)][k] + weight[k][j]);
                    }
                } 
                
            }
        }
        cout<<f[(1<<n)-1][n-1] <<endl;
        return 0;
    }

    异或:

    1. 可以帮助我们实现成对的思想。

    比如:0,1

    2,3

    4,5

    6,7

    异或1 : 可以帮助我们得到一对里的一个配偶。

    0^1 = 1, 1^1 = 0

    4^1 = 5, 5^1 = 4

    2. lowbit 运算:求一个数(二进制下)从后向前数直到遇到第一个’1’时的数 

    lowbit(1110010000) = 10000

    如 : 取反 : 0001101111 

    加1:0001110000

    (取反加1相当于取 1110010000的补码) ,将 1110010000 & 0001110000 就得到 10000

    int lowbit(n)

    {

      return (~n+1) &n;       // return (-n) & n;

  • 相关阅读:
    EM
    解决使用bootstrap modal时,icon-picker组件被遮挡问题
    记一次cpu100%问题排查过程
    docker安装nexus搭建maven私库
    记一次bootstrap table使用中的遭遇
    数据的逻辑结构与存储结构的基本概念(数据结构巩固一)
    前端js函数中直接获取springmvc后台model中传值
    springboot+vue部署后提示找不到css
    将springboot的jar包添加到windows服务及遇到的问题及其解决思路
    springboot打包jar后读取资源文件
  • 原文地址:https://www.cnblogs.com/Bella2017/p/11290882.html
Copyright © 2011-2022 走看看