快速幂

因为幂的性质

比如2^3可以转换成\(2^{1+2}\)也就是\(2^1* 2^2\)

根据这样我们其实就可以把一个大的幂次拆解成几个小的去计算

什么东西能将x拆开成几部分 且相加起来仍是x呢

显然 用二进制

还是以3为例 3 即11 它可以拆成 两个1

而且这两个1还是有关联的 左边这个1是右边那个1的平方

那么 就可以很容易地从低位开始 递推预处理出每一部分的值

(其实只需要算出第一个 然后每往左一位就是上一次的平方)

然而不是每一位都要取的 我们只需要取是1的即可

\(a^b\)中设\(b=2^{t1}+2^{t2}+…+2^{tk}\)(二进制)

image-87c4124d image-3ae7de18

其实意思就是\(2^{12}\)可以化成\(2^8*2^4\)

4和8怎么来的

第一轮 \(2^0\) 因为是该位的二进制为0所以不取

第二轮\({2^{0}}^2\)即\(2^2\) 为0 不取

第三轮 \({2^2}^2\)即\(2^4\) 为1 取

第四轮\({2^4}^2\)即 \(2^8\) 为1 取

至于为什么可以每轮都模p

其实就是一个交换律

(a%p)*(b%p)=(a*b)%p

所以何必要求到最大的时候统一模呢 每轮做就好了 还能防止爆数据

int qmi(int a, int b, int p)
{
    int res = 1 % p;
    while(b)
    {
        if (b & 1)
          res = (long long)res * a % p;
        a = (long long)a * a % p;//不管是0还是1 这一位都用过了 a是不断平方的
        b>>=1;
    }
    return res;
}
  • a^b

⬅️ 子集 🏠 00-刷题理模型 ➡️ a-b