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

    目录

    • 位运算前言
    • 位运算应用
      • 1 快速幂
      • 2 最大公约数
      • 3 xor 一些应用
      • 4 其他

    位运算前言

    程序中所有东西在计算机中都是以二进制储存的。

    位运算可以直接操作这些二进制。

    所以位运算相对于普通运算要

    这些是所有位运算及其优先级:

    注意区分逻辑运算和按位运算的区别,逻辑运算视所有 ( eq 0) 的数为 ( exttt{True})(1))。

    对于全体运算来说:

    运算
    逻辑非(not!);按位取反(~ )
    乘法(*);除法(/);取模(mod%
    加法(+);减法(-
    左移(<<);右移(>>
    大于(>)小于(<),大于等于(>=),小于等于(<=

    转进制IO

    一些格式化符:

    进制 iomanip 格式化符 printf 格式化符
    十进制 dec %d
    八进制 oct %o
    十六进制 hex %x

    注意 cin 的格式化符延长至整个程序,用 dec 恢复!!

    位运算应用

    1. 快速幂
    2. 最大公约数

    1 快速幂

    给定 (a,n) 计算 (a^n)

    最朴素的做法当然是 (mathcal{O}(n)) 暴力乘。

    typedef long long ll;
    ll power(ll a,int n)
    {
    	ll ans=1;
        for (int i=0;i<n;i++) ans*=a;
        return ans;
    }
    

    我们优化一下。

    如果我们计算 (7^{31})

    我们做一下变式:

    (egin{aligned} 7^{31}&=7^{2^0+2^1+2^2+3^3}\ &=7^{1+2+4+16}\ &=7^1 imes 7^2 imes 7^4 imes 7^{16} end{aligned})

    我们对于这个变式,考虑二进制拆分。

    (31) 正好分成了 (2) 的正整数次幂,是否所有数字都可以呢?

    尝试 (7^{11})(11=1+2+8),发现少了个 (4)

    (11=(1101)_2),每一个幂都乘此数的每一位即可。

    [11=2^{color{red}{1}color{black} imes 1} imes2^{color{red}{1}color{black} imes 2} imes 2^{color{red}{0}color{black} imes 3} imes 2^{color{red}{1}color{black} imes 4} ]

    所以这样模拟即可,(mathcal{O}(log n)) 时间复杂度。

    其中 (a^n) 可以用一个 ( exttt{base}=a^{n-1})( exttt{base}= exttt{base}* exttt{base}) 求得。

    typedef long long ll;
    ll qpow(ll a,ll b,ll mod)   //带上取模QAQ
    {
    	ll ans=1,base=a;
    	while (b)                         //没有乘完
    	{
    		if (b&1) ans*=base,ans%=mod;  //如果这一位为 1,自乘
    		base*=base;b>>=1;base%=mod;   //更新 base,进入下一位(b>>=1)
    	}
    	return ans%mod;    //如果 b=0,那么如果模数为 1 不加 %mod 就会 WA。
    }
    

    2 最大公约数

    众所周知有辗转相除法:

    [gcd(a,b)=gcd(b,amod\,b) ]

    朴素算法也就是这个,最坏被卡 (mathcal{O}(log n))

    int gcd(int a,int b){return b?gcd(b,a%b):a;}
    

    我们知道有更相减损术:

    [gcd(a,b)=gcd(b,a-b) ]

    我们能减半尽量要减半,具体看代码即可。

    typedef long long ll;
    ll gcd(ll a,ll b)  //优化后
    {
        if (b==0) return 0;    //特判
        if (a<b) return gcd(b,a); //交换顺序
        if (a==b) return b;    //边界
        if (a&1)    //如果 a 是奇数
        {
            if (b&1) return gcd(b,a-b); //如果 b 也是奇数,只能更相减损
            else return gcd(a,b>>1);  //b 是偶数,减半
        }
        else  //如果 a 是偶数 
        {
            if (b&1) return gcd(a>>1,b);  //b 是奇数,a 减半
            else return 2*gcd(a>>1,b>>1); //都是偶数,一起减半,答案 *2。
        }
    }
    

    3 xor 一些应用

    首先有个性质:

    x^0=xx^1=~x

    x^p^p=x,即异或为异或的逆运算。

    因异或为异或的逆运算,所以异或是唯一的可逆运算(位运算中)。

    所以可以进行简单加密:

    • 两人持有密钥
    • 第一人将自己的数字异或密钥后传至互联网
    • 第二人收到后再次异或密钥,获得原文。

    异或还可以做一个交换:

    a=a^b;b=a^b;a=a^b;
    

    缺点:

    1. 不能处理同一个变量

    总之,别用这种交换

    4 其他

    • 取二进制末 (k) 位:a&((1<<k)-1)
    • 取二进制第 (k) 位:(a>>(k-1))&1
    • 取二进制第一个 (1) 与后面的 (0) 组成的数字(( exttt{lowbit})):x&(-x)
    • 将最后一个 (1) 去除:x&=(x-1)
    • 将右数第 (k) 位置 (1)a=(a|(1<<(k-1)))
    • 将右数第 (k) 位置 (0)a&=1<<(k-1)
    • 将右数后 (k) 位置 (1)a&=(1<<(k+1))-1
    • 将右数后 (k) 位置 (0)a&=~((1<<(k+1))-1)
    • 将右数第 (k) 位取反:a^=(1<<k)
    • 将右数后 (k) 位取反:a^=((1<<(k+1))-1)

    • x==-1~x
    • x==0!x
    • x%2x&1
  • 相关阅读:
    Yield Usage Understanding
    Deadclock on calling async methond
    How to generate file name according to datetime in bat command
    Run Unit API Testing Which Was Distributed To Multiple Test Agents
    druid的关键参数+数据库连接池运行原理
    修改idea打开新窗口的默认配置
    spring boot -thymeleaf-url
    @pathvariable和@RequestParam的区别
    spring boot -thymeleaf-域对象操作
    spring boot -thymeleaf-遍历list和map
  • 原文地址:https://www.cnblogs.com/CDOI-24374/p/12853980.html
Copyright © 2011-2022 走看看