Skip to content

快速幂

快速幂算法可以在 O(logk) 时间内求出 akmodp 的结果。其中 a,p,k109。暴力做法至少要循环 k 次,时间复杂度为 O(k) 的。

反复平方法:

  • 预处理以下值:a2imodp,其中 i=0,1,,logk
  • 而根据 k 的二进制表示,例如 (11)10=(1011)2,是 1 的位就加上即可
  • 这里还有模的积性:若 aa1(modp),bb1(modp),那么 aba1b1(modp)(代入证明一下即可)

AC875. 快速幂

核心代码:

cpp
int qmi(int a, int k, int p) {
    int res = 1;
    while (k) {
        if (k & 1) {
            res = (LL)res * a % p;
        }

        k >>= 1;

        a = (LL)a * a % p;
    }
}
  • if (k & 1) 当末位数字是 1 时,乘以这个时候的 a2i(模了 p 之后的值)
  • 每次 k 都要右移一位
  • 每次 a 更新,其实就是自身 反复平方

其实:

  • 前面的是:res = (LL)res * (a % p);
  • 后面的是:a = (LL)(a * a) % p;

快速幂求逆元

逆元定义:若整数 b,m 互质,且对于任意整数 a,如果满足 b|a,那么存在一个整数 x,使得:

aba×x(modm)

同时称 xbm乘法逆元,记为 b1(modm)。整数 b 存在乘法逆元的充要条件是 b,m 互质。注意,这里的 x 只与 b,m 有关,与 a 怎么取无关。

证明:对上面式子两边同时乘以 b,因此有:

aabb1(modm)

由于乘法逆元与 a 怎么取无关,不妨设 (a,m)=1(注意到,如果取其他的 a 使得二者不互质,那么在互质条件下得到的后续条件也能使得这样的 a 满足上述等式)。当 (a,m)=1 后,两边同时删除 a,得到:

bb11(modm)

该条件对于不互质的 a 也有上上式子成立。属于是 必要条件

所谓的求逆元问题就是找到满足 bx1(modm)x

费马小定理

对于正整数 a 和素数 p,有:

apa(modp)

我们先证明一个引理:若 a1,a2,,amm 的一个完全剩余系,那么对于和它互质的整数 b 而言,ba1,ba2,,bam 也是 m 的一个完全剩余系。证明如下:只需要证明任意两个 bajm 不同余即可:

baibaj(modm)aiaj(modm)

这下直接矛盾。因此引理得证。而 1,2,,p1 正是素数 p 的一个完全剩余系,而对于不是 p 倍数的 a 而言显然有 (a,p)=1(如果 ap 的倍数,那么费马小定理原等式显然成立),因此新的 a,2a,,(p1)a 也是素数 p 的一个完全剩余系。因此将它们乘起来:

1×2××(p1)[a×2a××(p1)a](modp)

由于 (p1)! 显然和 p 互素,因此有:

ap11(modp)

这正是费马小定理的一个推论,前提是 (a,p)=1,如果扩展到任意正整数,那么就是费马小定理的原式。

回到原题,对于 (b,p)=1,那么 b 的逆元就是 bp2

AC876. 快速幂求逆元

Released under the MIT License.