快速幂 + 64位龟速乘法

快速幂

快速地求出 $ a^{b}\;mod\;p $, 其中 $ 1 \leq a,\,b,\,p \leq 10^{9} $ 

每一个正整数都有其唯一的二进制表示, 显然每一个正整数也都可以唯一地表示为若干指数不重复的2的次幂的和

即, 设 $b$ 在二进制表示下有 $k$ 位, 其中第 $i\,(0 \leq i < k)$ 位的数字是 $ c_{i} $, 则:

      $ b=c_{k-1}2^{k-1}+c_{k-2}2^{k-2}+...+c_{0}2^{0} $

    $ \Rightarrow  $

      $ a^{b} = a^{c_{k-1}\;2^{k-1}\;+\;c_{k-2}\;2^{k-2}\;+\;...\;+\;c_{0}\,2^{0}} $

又因为 $ a^{2^{i}} = (a^{2^{i-1}}\,)^{2} $, 我们可以通过 $k$ 次递推求出每一个乘积项, 当 $c_{i}=1$ 时, 将该乘积项累积到答案中

$b$ & 1可以取出b的最低位, 而 $b>>1$可以舍去 $b$ 的最低位, 二者结合可以遍历 $b$ 在二进制表示下的所有数位

由于 $b$ 的二进制表示的位数 $k$ 与$log\,b$ 同级, 所以整个算法的时间复杂度为 $O(log\,n)$

LL qmi(LL a, LL b, LL p) {
    LL ans = 1 % p;
    while(b) {
        if(b & 1) ans = ans * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return ans;
}

 

64位龟速乘法

求出 $ a \cdot b\;mod\;p $, 其中 $ 1 \leq a,\,b,\,p \leq 10^{18} $ 

同快速幂, 设 $b$ 在二进制表示下有 $k$ 位, 其中第 $i\,(0 \leq i < k)$ 位的数字是 $ c_{i} $, 则:

      $ b=c_{k-1}2^{k-1}+c_{k-2}2^{k-2}+...+c_{0}2^{0} $

    $ \Rightarrow  $

      $ a \cdot b = a\cdot(c_{k-1}\;2^{k-1}+c_{k-2}\;2^{k-2}+...+c_{0}2^{0}) $

       展开得 $ = a\cdot c_{k-1}\;2^{k-1}+ ... + a\cdot c_{0}2^{0} $

求法与快速幂几乎一样, 只是将 × 改为 +, 时间复杂度也相同, 为 $O(log n)$, 因此得名龟速乘

LL qmul(LL a, LL b, LL p) {
    LL ans = 0;
    while(b) {
        if(b & 1) ans = (ans + a) % p;
        a = (a + a) % p;
        b >>= 1;
    }
    return ans;
}

 

posted @ 2020-10-06 15:00  yikanji  阅读(183)  评论(0)    收藏  举报