高次剩余 & 单位根

数学 / 数论

本地源文件:docs/math__number-theory__residue.md

高次剩余 & 单位根

前置知识:离散对数

本文讨论模意义下的高次剩余和单位根,并介绍模意义下开方运算的算法.

高次剩余

模运算下的高次剩余,可以认为是在讨论模意义下开高次方的可行性.它是 二次剩余 的推广.

𝑘k 次剩余

令整数 𝑘 ≥2k≥2,整数 𝑎a 和正整数 𝑚m 互素.若存在整数 𝑥x 使得

𝑥𝑘≡𝑎(mod𝑚),xk≡a(modm),

则称 𝑎a 为模 𝑚m𝑘 k 次剩余(𝑘k-th residue),𝑥x 为 𝑎a 模 𝑚m𝑘 k 次方根(𝑘k-th root);否则称 𝑎a 为模 𝑚m𝑘 k 次非剩余(𝑘k-th nonresidue).

也就是说,𝑎a 模 𝑚m 的 𝑘k 次方根存在,当且仅当 𝑎a 是模 𝑚m 的 𝑘k 次剩余.

性质

类似二次剩余,可以讨论 𝑘k 次剩余的判定、个数以及 𝑘k 次剩余类的个数问题.和其他 同余方程 问题一样,可以通过 中国剩余定理 将它们转化为素数幂模的情形.根据原根的有无,这进一步区分为奇素数幂模和模数为 22 的幂次的情形.

奇数幂模的情形较为简单.事实上,对于所有原根存在的情形,都有如下结论:

定理

设整数 𝑘 ≥2k≥2,整数 𝑎a 和正整数 𝑚m 互素.设模 𝑚m 的原根存在,且 𝑔g 是模 𝑚m 的一个原根.记 𝑑 =gcd(𝑘,𝜑(𝑚))d=gcd(k,φ(m)) 且 𝑑′ =𝜑(𝑚)𝑑d′=φ(m)d,其中,𝜑(𝑚)φ(m)欧拉函数.那么,有:

  1. 𝑎a 为模 𝑚m 的 𝑘k 次剩余,当且仅当

𝑎𝑑′≡1(mod𝑚).ad′≡1(modm).

  1. 当 𝑎a 为模 𝑚m 的 𝑘k 次剩余时,同余意义下,𝑎a 模 𝑚m 恰有 𝑑d 个互不相同的 𝑘k 次方根,且它们具有形式

𝑥≡𝑔𝑦0+𝑖𝑑′(mod𝜑(𝑚)), 0≤𝑦0<𝑑′, 𝑖=0,1,⋯,𝑑−1.x≡gy0+id′(modφ(m)), 0≤y0<d′, i=0,1,⋯,d−1.

  1. 模 𝑚m 的 𝑘k 次剩余类的个数为 𝑑′d′,且它们的全体就是

{𝑔𝑑𝑖mod𝑚:0≤𝑖<𝑑′}.{gdimodm:0≤i<d′}.

证明

因为 𝑎 ⟂𝑚a⟂m,所以 𝑥 ⟂𝑚x⟂m.因为 𝑔g 是模 𝑚m 的原根,所以,𝑥x 和 𝑎a 均与某个 𝑔g 的幂次同余.设 𝑥 ≡𝑔𝑦(mod𝑚)x≡gy(modm),方程 𝑥𝑘 ≡𝑎(mod𝑚)xk≡a(modm) 就等价于

𝑔𝑘𝑦≡𝑔ind𝑔⁡𝑎(mod𝑚).gky≡gindg⁡a(modm).

其中,ind𝑔⁡𝑎indg⁡a 是离散对数.根据 阶的性质 和 𝛿𝑚(𝑔) =𝜑(𝑚)δm(g)=φ(m),这等价于同余方程

𝑘𝑦≡ind𝑔⁡𝑎(mod𝜑(𝑚)).ky≡indg⁡a(modφ(m)).

这是关于 𝑦y线性同余方程.应用该页面对其解结构的分析,就可以知道方程有解当且仅当 𝑑 ∣ind𝑔⁡𝑎d∣indg⁡a,且通解形式为

𝑦=𝑦0+𝑖𝑑′(mod𝜑(𝑚)), 0≤𝑦0<𝑑′, 𝑖=0,1,⋯,𝑑−1.y=y0+id′(modφ(m)), 0≤y0<d′, i=0,1,⋯,d−1.

由此,就几乎可以得到本定理的全部内容;唯一需要额外说明的是判别式 𝑎𝑑′ ≡1(mod𝑚)ad′≡1(modm).由 阶的性质 3 可知

𝛿𝑚(𝑎)=𝛿𝑚(𝑔ind𝑔⁡𝑎)=𝜑(𝑚)gcd(𝜑(𝑚),ind𝑔⁡𝑎)=𝜑(𝑚)ind𝑔⁡𝑎.δm(a)=δm(gindg⁡a)=φ(m)gcd(φ(m),indg⁡a)=φ(m)indg⁡a.

又已知方程有解当且仅当 𝑑 ∣ind𝑔⁡𝑎d∣indg⁡a,亦即 𝛿𝑚(𝑎) ∣𝑑′δm(a)∣d′.由 阶的性质 2 可知,这就等价于该判别式.

模数为 22 的幂次的情形较为特殊.为处理这种情形,需要用到关于模 2𝑒2e 既约剩余系结构的一个 结论:所有奇数 𝑎a 都唯一地同余于某个 ( −1)𝑠5𝑟mod2𝑒(−1)s5rmod2e 形式的整数,其中,𝑠 ∈{0,1}s∈{0,1} 且 0 ≤𝑟 <2𝑒−20≤r<2e−2.借助这一结果,可以得到如下结论:

定理

设整数 𝑘 ≥2k≥2,奇数 𝑎a 和正整数 𝑚 =2𝑒m=2e 且 𝑒 ≥2e≥2.那么,当 𝑘k 是奇数时,有:

  1. 𝑎a 恒为模 𝑚m 的 𝑘k 次剩余.
  2. 𝑎a 模 𝑚m 的 𝑘k 次方根有且仅有一个.
  3. 模 𝑚m 的 𝑘k 次剩余类个数为 2𝑒−12e−1,且它们就是全体既约剩余类.

当 𝑘k 是偶数时,记 𝑑 =gcd(𝑘,2𝑒−2)d=gcd(k,2e−2) 且 𝑑′ =2𝑒−2𝑑d′=2e−2d,有:

  1. 𝑎a 为模 𝑚m 的 𝑘k 次剩余,当且仅当 𝑎 ≡1(mod4)a≡1(mod4) 且 𝑎𝑑′ ≡1(mod𝑚)ad′≡1(modm)
  2. 当 𝑎a 为模 𝑚m 的 𝑘k 次剩余时,同余意义下,𝑎a 模 𝑚m 恰有 2𝑑2d 个互不相同的 𝑘k 次方根,且它们具有形式

𝑥≡±5𝑦0+𝑖𝑑′(mod2𝑒−1), 0≤𝑦0<𝑑′, 𝑖=0,1,⋯,𝑑−1.x≡±5y0+id′(mod2e−1), 0≤y0<d′, i=0,1,⋯,d−1.

  1. 模 𝑚m 的 𝑘k 次剩余类的个数为 𝑑′d′,且它们的全体就是

{5𝑑𝑖mod𝑚:0≤𝑖<𝑑′}.{5dimodm:0≤i<d′}.

证明

因为 𝑎 ⟂𝑚a⟂m,所以 𝑥 ⟂𝑚x⟂m.因为 𝑥x 和 𝑎a 都是奇数,由前述结论可知,可以设 𝑎 ≡( −1)𝑠5𝑟(mod2𝑒)a≡(−1)s5r(mod2e) 且 𝑥 =( −1)𝑧5𝑦(mod2𝑒)x=(−1)z5y(mod2e).因为表示是唯一的,所以同余方程 𝑥𝑘 ≡𝑎(mod2𝑒)xk≡a(mod2e) 等价于 线性同余方程

𝑘𝑧≡𝑠(mod2),𝑘𝑦≡𝑟(mod2𝑒−2).kz≡s(mod2),ky≡r(mod2e−2).

结合该页面对于线性同余方程解的分析,就可以得到同余方程 𝑥𝑘 ≡𝑎(mod2𝑒)xk≡a(mod2e) 解的结构.根据 𝑘k 的奇偶性不同,可以分为两种情形:

  • 当 𝑘k 是奇数时,因为 gcd(𝑘,2) =gcd(𝑘,2𝑒−2) =1gcd(k,2)=gcd(k,2e−2)=1,所以两个线性同余方程对于所有 𝑠,𝑟s,r 都有解,故而原同余方程对于所有奇数 𝑎a 总是有解.
  • 当 𝑘k 是偶数时,第一个方程有解当且仅当 2 ∣𝑠2∣s,第二个方程有解当且仅当 𝑑 =gcd(𝑘,2𝑒−2) ∣𝑟d=gcd(k,2e−2)∣r.将两者结合就得到 𝑘k 次剩余类的全体形式.直接计算可知,第一个条件等价于 𝑎 ≡1(mod4)a≡1(mod4);重复奇素数幂情形的分析可知,第二个条件等价于 𝑎𝑑′ =1ad′=1.将两点结合起来就得到定理中的判定方法.两个线性同余方程的通解也是已知的:

𝑧≡0,1(mod2),𝑦≡𝑦0+𝑖𝑑′(mod2𝑒−2), 0≤𝑦0<2𝑒−2.z≡0,1(mod2),y≡y0+id′(mod2e−2), 0≤y0<2e−2.

将两者结合就得到原方程的通解.

这就完全解决了不同模数下 𝑘k 次剩余的判定问题.二次剩余中的 Legendre 记号和二次互反律等内容也可以推广到高次剩余的情形,但这并不容易,需要用到 分圆域 等概念.在代数数论中,二次互反律最终可以推广到 Artin 互反律

单位根

作为 𝑘k 次方根的特殊情形,本节讨论 𝑘k 次(本原)单位根的概念.它可以看作是复数域 𝐂C 中 𝑘k单位根 的概念在模 𝑚m 既约剩余系 𝐙∗𝑚Zm∗ 中的对应.当模数 𝑚m 合适时,用模 𝑚m 的 𝑘k 次本原单位根代替复数根 𝜔𝑘ωk 可以加速计算.

类似于复数域的情形,有如下定义:

模 𝑚m 的 𝑘k 次单位根

对于模数 𝑚m,元素 11 的 𝑘k 次方根称为 模 𝑚m 的 𝑘k 次单位根(𝑘k-th root of unity modulo 𝑚m).特别地,如果 𝑥x 是模 𝑚m 的一个 𝑘k 次单位根,且它不是模 𝑚m 的任何 𝑘′ <𝑘k′<k 次单位根,那么,也称 𝑥x模 𝑚m 的 𝑘k 次本原单位根(𝑘k-th primitive root of unity modulo 𝑚m).

比较 原根的定义 可知,原根 𝑔g 就是模 𝑚m 的 𝜑(𝑚)φ(m) 次本原单位根,其中,𝜑(𝑚)φ(m)欧拉函数

当模 𝑚m 的 𝑘k 次本原单位根存在时,它的代数性质和 𝑘k 次本原单位复根 𝜔𝑘ωk 一致,可以代替 𝜔𝑘ωk 进行各种计算.例如,将它应用于 快速傅里叶变换 中,就得到有限域1上的 快速数论变换

性质

复数域中,任意次(本原)单位根都存在.但是,数论中的(本原)单位根并非如此.

性质

对于模数 𝑚m,设 𝜆(𝑚)λ(m) 为它的 Carmichael 函数,有:

  1. 所有与 𝑚m 互素的整数 𝑎a 都是模 𝑚m 的 𝛿𝑚(𝑎)δm(a) 次本原单位根,其中,𝛿𝑚(𝑎)δm(a) 是 𝑎a 模 𝑚m
  2. 元素 𝑎a 是模 𝑚m 的 𝑘k 次单位根,且 𝑘′k′ 是 𝑘k 的任意倍数,那么 𝑎a 也是模 𝑚m 的 𝑘′k′ 次单位根.
  3. 元素 𝑎a 是模 𝑚m 的 𝑘k 次(本原)单位根,那么元素 𝑎ℓaℓ 是模 𝑚m 的 𝑘gcd(𝑘,ℓ)kgcd(k,ℓ) 次(本原,相应地)单位根.
  4. 当 𝑘′k′ 遍历 𝑘k 的因数,所有模 𝑚m 的 𝑘′k′ 次本原单位根恰构成模 𝑚m 的 𝑘k 次单位根的一个划分.而且,对于 ℓ ⟂𝑘ℓ⟂k,映射 𝑥 ↦𝑥ℓx↦xℓ 给出 𝑘k 次单位根之间的双射,且保持上述划分不变:它将 𝑘′ ∣𝑘k′∣k 次本原单位根仍然映射到 𝑘′k′ 次本原单位根.
  5. 模 𝑚m 的 𝑘k 次本原单位根存在,当且仅当 𝑘 ∣𝜆(𝑚)k∣λ(m).特别地,模 𝑚m 的 𝜆(𝑚)λ(m) 次本原单位根存在,称为 模 𝑚m 的 𝜆λ‑原根
  6. 元素 𝑎a 是模 𝑚m 的 𝑘k 次单位根,当且仅当 𝑎𝑘 ≡1(mod𝑚)ak≡1(modm) 且对于任意素因子 𝑝 ∣𝑘p∣k 都有 𝑎𝑘/𝑝 ≢1(mod𝑚)ak/p≢1(modm)

证明

根据阶的定义,所有与 𝑚m 互素的整数 𝑎a 都是模 𝑚m 的 𝛿𝑚(𝑎)δm(a) 次本原单位根,其中,𝛿𝑚(𝑎)δm(a) 是 𝑎a 模 𝑚m 的阶.反过来,如果 𝑎a 是模 𝑚m 的 𝑘k 次单位根,那么 gcd(𝑎𝑘,𝑚) =1gcd(ak,m)=1,所以 gcd(𝑎,𝑚) =1gcd(a,m)=1.因此,𝑎a 是模 𝑚m 的(本原)单位根,当且仅当 𝑎a 与 𝑚m 互素.这就是性质 1.

直接验证定义可知,只要 𝑘 ∣𝑘′k∣k′,就可以从 𝑎𝑘 ≡1(mod𝑚)ak≡1(modm) 推出 𝑎𝑘′ ≡1(mod𝑚)ak′≡1(modm),这就是性质 2.根据 阶的性质 可知

𝛿(𝑎ℓ)=𝛿𝑚(𝑎)gcd(𝛿𝑚(𝑎),ℓ).δ(aℓ)=δm(a)gcd(δm(a),ℓ).

如果 𝑎a 是模 𝑚m 的 𝑘k 次本原单位根,那么,𝛿𝑚(𝑎) =𝑘δm(a)=k,直接代入上式就得到 𝑎ℓaℓ 是模 𝑚m 的 𝑘gcd(𝑘,ℓ)kgcd(k,ℓ) 次本原单位根.如果 𝑎a 只是模 𝑚m 的 𝑘k 次单位根,设它是 𝑘′ ∣𝑘k′∣k 次本原单位根,故而 𝑎ℓaℓ 是模 𝑚m 的 𝑘′gcd(𝑘′,ℓ)k′gcd(k′,ℓ) 次本原单位根.由于 𝑘′ ∣𝑘k′∣k,有

𝑘′gcd(𝑘′,ℓ)∣𝑘gcd(𝑘,ℓ),k′gcd(k′,ℓ)∣kgcd(k,ℓ),

再由性质 2,就得到 𝑎ℓaℓ 是模 𝑚m 的 𝑘gcd(𝑘,ℓ)kgcd(k,ℓ) 次单位根.这就是性质 3.

对于 𝑘′ ∣𝑘k′∣k,由性质 2,模 𝑚m 的 𝑘′k′ 次本原单位根必然是模 𝑚m 的 𝑘k 次单位根.它们两两不交,故而构成划分.而对于 ℓ ⟂𝑘ℓ⟂k,总有 ℓ ⟂𝑘′ℓ⟂k′,因此对于模 𝑚m 的 𝑘′k′ 次本原单位根 𝑎a,总有 𝑎ℓaℓ 是模 𝑚m 的 𝑘′k′ 次本原单位根.取 ℓ′ =ℓ−1mod𝑘ℓ′=ℓ−1modk,可以验证 𝑥 ↦𝑥ℓx↦xℓ 和 𝑥 ↦𝑥ℓ′x↦xℓ′ 互为逆映射,因此,𝑥 ↦𝑥ℓx↦xℓ 是双射.这就是性质 4.

根据 Carmichael 函数的性质可知,模 𝑚m 的 𝜆(𝑚)λ(m) 次本原单位根总是存在的,设它为 𝑎a,且 𝛿𝑚(𝑎) =𝜆(𝑚)δm(a)=λ(m).对于 𝑘 ∣𝜆(𝑚)k∣λ(m),设 𝑘′ =𝜆(𝑚)𝑘k′=λ(m)k,总有

𝛿𝑚(𝑎𝑘′)=𝜆(𝑚)(𝜆(𝑚),𝑘′)=𝜆(𝑚)𝑘′=𝑘.δm(ak′)=λ(m)(λ(m),k′)=λ(m)k′=k.

因此,𝑎𝑘′ak′ 是 𝑘k 次本原单位根.而根据 Carmichael 函数的定义,所有 𝑥 ⟂𝑚x⟂m 的阶都是 𝜆(𝑚)λ(m) 的因子.这就得到性质 5.

几乎重复 原根判定定理 的证明,就可以得到性质 6.这一判别方法实际上在验证 𝛿𝑚(𝑎) =𝑘δm(a)=k

从这些性质可以看出,相对于原根存在的情形,模 𝑚m 的 𝜆λ‑原根起到了类似的基础作用.与原根不同的是,𝜆λ‑原根的幂次并不能用于生成模 𝑚m 的全体单位根.尽管如此,由于 𝜆λ‑原根的密度并不低2,如果确实需要找到 𝑘k 次本原单位根,可以首先通过随机方法找到一个 𝜆λ‑原根,再通过求幂次得到一个 𝑘k 次本原单位根.

如果已知 𝑎a 模 𝑚m 的一个 𝑘k 次方根,可以通过模 𝑚m 的全体 𝑘k 次单位根生成 𝑎a 模 𝑚m 的全体 𝑘k 次方根.

定理

设 𝑥x 是 𝑎a 模 𝑚m 的一个 𝑘k 次方根,当 𝑟r 遍历模 𝑚m 的全体 𝑘k 次单位根时,𝑥𝑟xr 遍历 𝑎a 模 𝑚m 的全体 𝑘k 次方根.

证明

对于 𝑎a 模 𝑚m 的两个 𝑘k 次方根 𝑥,𝑦x,y,设 𝑟 =𝑥−1𝑦mod𝑚r=x−1ymodm,那么 𝑟r 满足 𝑟𝑘 ≡1(mod𝑚)rk≡1(modm),是模 𝑚m 的 𝑘k 次方根.反过来,只要 𝑟r 是模 𝑚m 的 𝑘k 次单位根,那么,(𝑥𝑟)𝑘 =𝑥𝑘𝑟𝑘 ≡𝑎(mod𝑚)(xr)k=xkrk≡a(modm),也就是说,𝑥𝑟xr 是模 𝑚m 的 𝑘k 次方根.

利用 𝑘k 次单位根生成全体 𝑘k 次方根,就类似于利用齐次线性方程组的解生成非齐次线性方程组的通解一样.

前面讨论的是一般情形.仅对于原根存在的情形,单位根的结构更为简单:

定理

对于模数 𝑚m,设模 𝑚m 的原根存在,且 𝑎a 是模 𝑚m 的 𝑘k 次本原单位根.那么,𝑏b 是模 𝑚m 的 𝑘k 次单位根,当且仅当它可以表示为 𝑎a 的幂次.

证明

设 𝑔g 是模 𝑚m 的原根,那么,所有与 𝑚m 互素的元素都可以表示为 𝑔g 的幂次.那么,𝑎a 是模 𝑚m 的 𝑘k 次本原单位根,当且仅当

𝛿𝑚(𝑎)=𝛿𝑚(𝑔ind𝑔⁡𝑎)=𝜑(𝑚)gcd(𝜑(𝑚),ind𝑔⁡𝑎)=𝑘.δm(a)=δm(gindg⁡a)=φ(m)gcd(φ(m),indg⁡a)=k.

类似地,𝑏b 是模 𝑚m 的 𝑘k 次单位根,当且仅当

𝛿𝑚(𝑏)=𝛿𝑚(𝑔ind𝑔⁡𝑏)=𝜑(𝑚)gcd(𝜑(𝑚),ind𝑔⁡𝑏)=𝑘′∣𝑘.δm(b)=δm(gindg⁡b)=φ(m)gcd(φ(m),indg⁡b)=k′∣k.

所以,有

gcd(𝜑(𝑚),ind𝑔⁡𝑎)∣gcd(𝜑(𝑚),ind𝑔⁡𝑏)∣ind𝑔⁡𝑏.gcd(φ(m),indg⁡a)∣gcd(φ(m),indg⁡b)∣indg⁡b.

根据对线性同余方程的 分析 可知,这一条件就等价于方程

(ind𝑔⁡𝑎)𝑥≡ind𝑔⁡𝑏(mod𝜑(𝑚))(indg⁡a)x≡indg⁡b(modφ(m))

有解.将这一条件对 𝑔g 取幂,就得到 𝑎𝑥 ≡𝑏(mod𝑚)ax≡b(modm),亦即 𝑏b 可以表示为 𝑎a 的幂次.

这一定理说明,原根存在时,全体 𝑘k 次单位根呈现 循环群 的结构,而 𝑘k 次本原单位根则是该循环群的生成元.稍后将会看到,Tonelli–Shanks 算法正是利用这一点,加速了开方运算中离散对数部分的计算.

模意义下开方

最后,本文讨论 𝑘k 次方根的求法.对于 𝑘 =2k=2 的情形,有 很多高效算法 可以用于模意义下开平方运算.但是,对于一般的 𝑘k,并没有已知的多项式时间算法.本节将介绍两种常见算法,分别可以在 𝑂(𝑚1/2)O(m1/2) 和 𝑂(𝑚1/4+𝜀)O(m1/4+ε) 时间内求出一个 𝑘k 次方根.利用中国剩余定理总是可以将问题转换为素数幂模的情形,因此,本节主要讨论素数幂模情形的解法.

朴素算法

前文对于 𝑘k 次剩余性质的 分析 实际上已经指出了一种求解素数幂模下 𝑘k 次方根的方法.严格来说,前文解决的情形是被开方数 𝑎a 与模数 𝑚m 互素的情形.算法过程总结如下:

  • 当 𝑚 =𝑝𝑒m=pe 是奇素数幂时,设模 𝑚m 的一个原根是 𝑔g.那么,方程 𝑥𝑘 ≡𝑎(mod𝑚)xk≡a(modm) 可以转化为线性同余方程

𝑘𝑦≡ind𝑔⁡𝑎(mod𝜑(𝑚)).ky≡indg⁡a(modφ(m)).

其中,ind𝑔⁡𝑎indg⁡a 可以通过 BSGS 算法 求出,而 线性同余方程 的全体解容易求出.由此,就可以得到 𝑎a 的全部 𝑘k 次方根 𝑥 ≡𝑔𝑦(mod𝑚)x≡gy(modm)

除此之外,还有另一种相仿的思路.同样是设 𝑥 ≡𝑔𝑦(mod𝑚)x≡gy(modm),还可以通过变形

𝑥𝑘≡(𝑔𝑘)𝑦≡𝑎(mod𝑚)xk≡(gk)y≡a(modm)

转化为求底数为 𝑔𝑘gk 时 𝑎a 的离散对数.这同样可以通过 BSGS 算法找到一组特解.它的通解可以通过前文的解的表达式求出,也就是将特解与全体 𝑘k 次单位根逐一相乘得到.

无论采用哪种思路,原根已知时,该算法求出单个解的复杂度都是 𝑂(𝑚1/2)O(m1/2).因为可以在 𝑜(𝑚1/2)o(m1/2) 时间内找到一个原根,所以,总的时间复杂度仍然是 𝑂(𝑚1/2)O(m1/2)

  • 当 𝑚 =2𝑒m=2e 且 𝑒 ∈𝐍+e∈N+ 时,可以首先求出 𝑎 ≡( −1)𝑠5𝑟(mod𝑚)a≡(−1)s5r(modm) 中的 𝑠,𝑟s,r.这两个指数中,𝑠s 可以在 𝑂(1)O(1) 时间内确定:

𝑠={0,𝑎≡1(mod4),1,𝑎≡3(mod4).s={0,a≡1(mod4),1,a≡3(mod4).

而 𝑟 =ind5⁡(( −1)𝑠𝑎)r=ind5⁡((−1)sa) 可以通过 BSGS 算法在 𝑂(𝑚1/2)O(m1/2) 时间内求出.接下来,只需要求解线性同余方程组:

𝑘𝑧≡𝑠(mod2),𝑘𝑦≡𝑟(mod2𝑒−2).kz≡s(mod2),ky≡r(mod2e−2).

这个线性方程组的通解 (𝑧,𝑦)(z,y) 容易求出,而 𝑥 =( −1)𝑧5𝑦x=(−1)z5y 就是所求的方根.这一算法求出单个解的复杂度仍然是 𝑂(𝑚1/2)O(m1/2)

当然,对于无解的情形,其实可以通过前文叙述的判别方法在 𝑂(log⁡𝑚)O(log⁡m) 时间内快速判断,而无需在求解过程中判断.

求素数模 𝑘k 次方根的参考实现如下:(代码仅作示意,由于时间复杂度过高,无法通过本题)

模板题 Library Checker - Kth Root (Mod) 参考实现

---|---

### 改良 Tonelli–Shanks 算法

将用于模意义下开平方的 [Tonelli–Shanks 算法](../quad-residue/#tonellishanks-算法) 做适当推广,就可以解决素数幂模下开方运算.一种较为直接的推广方式是 Adleman–Manders–Miller 算法3,但是它的复杂度仍然不够优秀4.本节介绍由 sugarknri、Min_25、37zigen 等人提出的改良 Tonelli–Shanks 算法.它可以在 𝑂(𝑚1/4+𝜀)O(m1/4+ε)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 时间内求出一个 𝑘k![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次方根.

Tonelli–Shanks 算法的核心想法是,将离散对数的求解放到阶为 2𝑒2e![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的群里,进而降低时间复杂度.类似地,对于任意素数幂 𝑝𝑒pe![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 阶群内的离散对数,同样可以较为高效地求解,但是算法的复杂度为 Ω(√𝑝)Ω(p)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).Adleman–Manders–Miller 算法将 𝑘k![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次方根的求解分拆为多个素数幂阶群内离散对数的计算,但是受限于 𝑘k![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的最大素因子 𝑝max(𝑘)pmax(k)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的大小,算法复杂度仍然为 Ω(√𝑝max(𝑘))Ω(pmax(k))![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).本节算法进一步改良了这一过程,避免了对较大的素因子计算离散对数,进而将整体复杂度控制到 𝑂(𝑚1/4+𝜀)O(m1/4+ε)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).

#### 过程

考虑素数幂模 𝑚m![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 下 𝑎a![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的 𝑘k![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次方根的计算,即求解同余方程:

𝑥𝑘≡𝑎(mod𝑚).xk≡a(modm).![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

特别地,对于 𝑚 =2𝑒m=2e![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的情形,还需要保证 𝑎 ≡1(mod4)a≡1(mod4)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),进而 𝑎a![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 可以写成 𝑔 =5g=5![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的幂次.类似前文讨论,模 2𝑒2e![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 下 𝑘k![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次方根的计算总是可以转化为这样的情形.处理模 2𝑒2e![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的情形时,本节提到的 𝜑(𝑚)φ(m)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 都应换作 𝛿𝑚(5) =2𝑒−2δm(5)=2e−2![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).

首先,问题可以转化为开方次数整除 𝜑(𝑚)φ(m)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的情形.设 𝑑 =gcd(𝑘,𝜑(𝑚))d=gcd(k,φ(m))![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).那么,由 𝑘k![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次剩余的性质可知,当 𝑎a![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 模 𝑚m![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 是 𝑘k![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次剩余时,𝑎a![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 总是模 𝑚m![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的 𝜑(𝑚)𝑑φ(m)d![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次单位根.根据单位根的性质,对于任意 ℓ ⟂𝜑(𝑚)𝑑ℓ⟂φ(m)d![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),映射 𝑥 ↦𝑥ℓx↦xℓ![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 都是 𝜑(𝑚)𝑑φ(m)d![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次单位根之间的双射.因此,可以取

ℓ=(𝑘𝑑)−1mod𝜑(𝑚)𝑑.ℓ=(kd)−1modφ(m)d.![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

将原来的同余方程两侧同时取 ℓℓ![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次幂,就得到

𝑥𝑑≡𝑥𝑘ℓ≡𝑎ℓ=:𝑏(mod𝑚).xd≡xkℓ≡aℓ=:b(modm).![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

最左侧同余号利用了 [欧拉定理](../fermat/#欧拉定理) 和如下同余关系:(𝑐 ∈𝐙c∈Z![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7))

𝑘ℓ=𝑑(𝑘𝑑ℓ)=𝑑(𝑐𝜑(𝑚)𝑑+1)≡𝑑(mod𝜑(𝑚)).kℓ=d(kdℓ)=d(cφ(m)d+1)≡d(modφ(m)).![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

对于转化后的问题,考虑 𝑑d![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的素因数分解:

𝑑=∏𝑝∈𝐏𝑝𝑒.d=∏p∈Ppe.![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

可以从 𝑏 =𝑎ℓb=aℓ![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 开始,对每个 𝑝𝑒 ≠1pe≠1![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),依次开 𝑝𝑒pe![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次方,最后就能得到 𝑏b![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的 𝑑d![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次方根,也就是 𝑎a![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的 𝑘k![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次方根.

最后,问题转化为如何求如下方程的解:

𝑥𝑝𝑒≡𝑏(mod𝑚).xpe≡b(modm).![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

不妨设 𝜑(𝑚) =𝑝𝑠𝑟φ(m)=psr![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 且 𝑝 ⟂𝑟p⟂r![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).设 𝑞 ∈𝐍+q∈N+![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 是方程 𝑞𝑟 ≡ −1(mod𝑝𝑒)qr≡−1(modpe)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的解.那么,因为 𝑏b![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 是 𝑟𝑝𝑠−𝑒rps−e![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次单位根,所以 𝑏𝑞𝑟bqr![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 一定是 𝑝𝑠−𝑒ps−e![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次单位根.又设 𝜁ζ![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 是模 𝑚m![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的 𝑝𝑠ps![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次本原单位根.那么,𝜁𝑝𝑒ζpe![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 是 𝑝𝑠−𝑒ps−e![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次本原单位根,进而存在 ℎ ∈𝐍h∈N![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 使得 𝑏𝑞𝑟 ≡𝜁ℎ𝑝𝑒(mod𝑚)bqr≡ζhpe(modm)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).所以,直接验证可知

𝑥≡𝑏(𝑞𝑟+1)/𝑝𝑒𝜁−ℎ(mod𝑚)x≡b(qr+1)/peζ−h(modm)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

是 𝑏b![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 模 𝑚m![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的 𝑝𝑒pe![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次方根.

为了计算 𝑥x![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),需要找到模 𝑚m![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的一个 𝑝p![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次非剩余 𝜂η![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).为此,由前文性质,只需要随机 𝜂 ⟂𝑚η⟂m![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 并验证 𝜂𝜑(𝑚)/𝑝mod𝑚 ≠1ηφ(m)/pmodm≠1![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 即可.这样的数的密度是

𝜑(𝑚)𝑚(1−1𝑝)≥14.φ(m)m(1−1p)≥14.![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

因此,期望随机不超过 44![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 个整数就能找到它.注意到,𝜂𝑟𝑝𝑠−1 ≢1(mod𝑚)ηrps−1≢1(modm)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 且 𝜂𝑟𝑝𝑠 ≡1(mod𝑚)ηrps≡1(modm)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),所以,如果设 𝜁 =𝜂𝑟mod𝑚ζ=ηrmodm![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 和 𝜉 =𝜂𝑟𝑝𝑠−1mod𝑚ξ=ηrps−1modm![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),那么它们分别是 𝑝𝑠ps![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次和 𝑝p![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次本原单位根.

最后,需要计算 ℎ ∈𝐍h∈N![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).显然,可以取 ℎ <𝑝𝑠−𝑒h<ps−e![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).考虑 ℎh![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的 𝑝p![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 进制表示:

ℎ=𝑠−𝑒−1∑𝑗=0ℎ𝑗𝑝𝑗=ℎ0+ℎ1𝑝+ℎ2𝑝2+⋯.h=∑j=0s−e−1hjpj=h0+h1p+h2p2+⋯.![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

逐位计算这些数位.当前 𝑗j![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 个数位都计算完成时,必然有

(𝑏𝑞𝑟𝜁−𝑝𝑒(ℎ0+ℎ1𝑝+⋯+ℎ𝑗−1𝑝𝑗−1))𝑝𝑠−𝑒−𝑗−1≡𝜁ℎ𝑗𝑝𝑠−1≡𝜉ℎ𝑗(mod𝑚).(bqrζ−pe(h0+h1p+⋯+hj−1pj−1))ps−e−j−1≡ζhjps−1≡ξhj(modm).![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

故而,ℎ𝑗hj![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 可以通过计算关于 𝜉ξ![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的离散对数求出.为了获得更好的时间复杂度,需要使用 BSGS 算法.总共需要计算 (𝑠 −𝑒)(s−e)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次离散对数,设预处理 𝐵B![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 个 𝜉ξ![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的幂次,则单次求解离散对数的时间复杂度为 𝑂(𝑝/𝐵)O(p/B)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),总的时间复杂度为

𝑂(𝐵+(𝑠−𝑒)𝑝𝐵).O(B+(s−e)pB).![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

当 𝐵 =√(𝑠−𝑒)𝑝B=(s−e)p![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 时,总的时间复杂度最低,为 𝑂(√(𝑠−𝑒)𝑝)O((s−e)p)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).得到 ℎh![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 之后,代入前文 𝑥x![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的表达式,就可以找到一个特解.

#### 时间复杂度

这一算法的时间复杂度为 𝑂(𝑚1/4+𝜀)O(m1/4+ε)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).本节讨论复杂度时,总是假设单次乘法需要 𝑂(1)O(1)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 时间,且计算幂次时,总是应用欧拉定理降幂,则涉及的单个幂的计算总是可以在 𝑂(log⁡𝑚)O(log⁡m)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 时间内完成.

先考虑单个 𝑝𝑒pe![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次方根的计算.找到 𝑝p![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次非剩余只需要验证期望 𝑂(1)O(1)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 个数,总时间复杂度为 𝑂(log⁡𝑚)O(log⁡m)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).计算 𝑠,𝑟,𝜁,𝜂,𝑏𝑞𝑟s,r,ζ,η,bqr![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 各只需要 𝑂(log⁡𝑚)O(log⁡m)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 时间.计算 ℎh![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 时,单个数位需要通过 𝑂(log⁡𝑚)O(log⁡m)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 时间计算幂次,总共 (𝑠 −𝑒)(s−e)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 位,故而总的时间复杂度为 𝑂((𝑠 −𝑒)log⁡𝑚)O((s−e)log⁡m)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).前文已经说明,计算离散对数的部分预处理和 (𝑠 −𝑒)(s−e)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次查询的总时间为 𝑂(√(𝑠−𝑒)𝑝)O((s−e)p)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).因为 𝑠 −𝑒 ∈𝑂(log⁡𝑚)s−e∈O(log⁡m)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),所以单个 𝑝𝑒pe![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次方根的计算的时间复杂度为 𝑂(𝑝1/2+𝜀)O(p1/2+ε)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).特别地,当 𝑠 =𝑒s=e![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 时,时间复杂度可以进一步减少为 𝑂(log⁡𝑚)O(log⁡m)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).

进而,可以考虑算法总的时间复杂度.计算 𝜑(𝑚),𝑑,ℓφ(m),d,ℓ![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的时间复杂度均为 𝑂(log⁡𝑚)O(log⁡m)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).紧接着需要做素因数分解 𝑑 =∏𝑝𝑝𝑒d=∏ppe![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),这一步利用 [Pollard Rho 算法](../pollard-rho/#pollard-rho-算法) 可以在 𝑂(𝑚1/4)O(m1/4)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 时间内完成.最后,依次求 𝑝𝑒pe![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次方根的总时间复杂度为

𝑂(∑𝑒<𝑠𝑝1/2+𝜀).O(∑e<sp1/2+ε).![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

由于满足 𝑒 <𝑠e<s![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的素因子 𝑝p![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 至少在 𝜑(𝑚)φ(m)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 中出现 22![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次,必然有 𝑝 <𝑚1/2p<m1/2![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).故而,总时间复杂度为 𝑂(𝑚1/4+𝜀)O(m1/4+ε)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).

事实上,在这一情景中,无需使用 Pollard Rho 算法分解素因数,仍然可以获得 𝑂(𝑚1/4+𝜀)O(m1/4+ε)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的时间复杂度.事实上,只需要对 𝑑d![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 暴力试除进行分解,并只枚举到不超过 𝑚1/4m1/4![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的素因子.设去除这些小素因子后得到的整数为 𝑧z![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).那么,对于 𝑧z![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的素因子 𝑝 >𝑚1/4p>m1/4![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),必然有 𝜈𝑝(𝜑(𝑚)) <4νp(φ(m))<4![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),其中,𝜈𝑝(𝑛)νp(n)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 表示 𝑛n![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的素因数分解中 𝑝p![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的次数.由于只需要考虑

1≤𝑒=𝜈𝑝(𝑑)<𝑠=𝜈𝑝(𝜑(𝑚))<41≤e=νp(d)<s=νp(φ(m))<4![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

的情形,满足该条件的素因子 𝑝p![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 至多只能有一个;否则,它们在 𝜑(𝑚)φ(m)![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 中的次数都不小于 22![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),总的乘积必然超过 𝑚m![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7).要分离出这个(可能存在的)唯一的大素因子,只需要计算

𝑝⋆=gcd(𝑧,𝜑(𝑚)𝑧)=∏𝑝:𝜈𝑝(𝑑)<𝜈𝑝(𝜑(𝑚))𝑝min{𝜈𝑝(𝑑),𝜈𝑝(𝜑(𝑚))−𝜈𝑝(𝑑)}.p⋆=gcd(z,φ(m)z)=∏p:νp(d)<νp(φ(m))pmin{νp(d),νp(φ(m))−νp(d)}.![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)

枚举 𝜈𝑝(𝑑),𝜈𝑝(𝜑(𝑚))νp(d),νp(φ(m))![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的所有可能性可知,乘积中 𝑝p![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的次数一定是 11![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),因此这样算出来的就是唯一的大素因子 𝑝⋆p⋆![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)(如果存在的话).至于剩余的部分 𝑧/𝑝⋆z/p⋆![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7),因为其中只能包含若干满足 𝑒 =𝑠e=s![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 的素因子,所以无需继续分解.

求素数模 𝑘k![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) 次方根的参考实现如下:

模板题 [Library Checker - Kth Root (Mod)](https://judge.yosupo.jp/problem/kth_root_mod) 参考实现

---|---

一般情形的处理

考虑一般的情形,仍然设模数 𝑚m 是素数幂 𝑝𝑒pe,但是 gcd(𝑎,𝑚) >1gcd(a,m)>1.如果 𝑎 ≡0(mod𝑚)a≡0(modm),那么

𝑥=𝑝⌈𝑒/𝑘⌉ℓ(mod𝑝𝑒), ℓ=0,1,⋯,𝑝𝑒−⌈𝑒/𝑘⌉−1x=p⌈e/k⌉ℓ(modpe), ℓ=0,1,⋯,pe−⌈e/k⌉−1

都是原方程的解.接下来,考察 𝑎 ≢0(mod𝑚)a≢0(modm) 的情形.设 𝑎 =𝑝𝑠𝑎′a=psa′ 且 𝑝 ⟂𝑎′p⟂a′.于是,设 𝑥 =𝑝𝑧𝑥′x=pzx′ 且 𝑝 ⟂𝑥′p⟂x′,就有

𝑥𝑘=𝑝𝑘𝑧(𝑥′)𝑘≡𝑝𝑠𝑎′(mod𝑝𝑒).xk=pkz(x′)k≡psa′(modpe).

由于 (𝑥′)𝑘 ⟂𝑝(x′)k⟂p,所以该式成立当且仅当 𝑘𝑧 =𝑠kz=s 且 (𝑥′)𝑘 ≡𝑎′(mod𝑝𝑒−𝑠)(x′)k≡a′(modpe−s).当且仅当 𝑘 ∣𝑠k∣s 时,第一个方程有解 𝑧 =𝑠𝑘z=sk;而第二个方程的求解已经解决.需要注意的是,因为第二个方程的通解的模数与原方程通解的模数并不相同,所以第二个方程的每一个解 𝑥′x′,都对应原方程的若干解:

𝑥≡𝑝𝑠/𝑘(𝑥′+ℓ𝑝𝑒−𝑠)(mod𝑝𝑒), ℓ=0,1,⋯,𝑝𝑠−𝑠/𝑘−1.x≡ps/k(x′+ℓpe−s)(modpe), ℓ=0,1,⋯,ps−s/k−1.

求解任一模数下全体 𝑘k 次方根的参考实现如下:

模板题 Luogu P5668【模板】N 次剩余 参考代码

朴素算法改良 Tonelli–Shanks 算法

---|---

---|---

参考资料与注释

  1. 实际上,模数 𝑚m 未必是素数.只要 𝑎a 是模 𝑚m 的 𝑘 =2𝑒k=2e 次本原单位根,就可以用于模 𝑚m 的快速数论变换.但是,由于通常需要处理的 2𝑒2e 比较大,这意味着模数 𝑚m 中的每个素因子都是 𝑐2𝑒 +1c2e+1 形式.因此,单个素因子就很大,而模数 𝑚m 通常会更大,因而一般模数的情形并没有素数模的情形常用. ↩
  1. 根据 原根个数相关结论 可知,𝜆λ‑原根的数量恰为 𝜑(𝜆(𝑚))φ(λ(m)),其中,𝜑( ⋅)φ(⋅) 和 𝜆( ⋅)λ(⋅) 分别是欧拉函数和 Carmichael 函数.因为对于几乎所有整数 𝑚m,都有 𝜆(𝑚)/𝑚 =exp⁡(−(1+𝑜(1))log⁡log⁡𝑚log⁡log⁡log⁡𝑚)λ(m)/m=exp⁡(−(1+o(1))log⁡log⁡mlog⁡log⁡log⁡m),而存在 𝐶 >0C>0,使得对于整数 𝑚 >2m>2,都有 𝜑(𝑚)/𝑚 =𝐶/log⁡log⁡𝑚φ(m)/m=C/log⁡log⁡m,所以,对于几乎所有整数 𝑚m,都有 𝜑(𝜆(𝑚))/𝑚 =exp⁡(−(1+𝑜(1))log⁡log⁡𝑚log⁡log⁡log⁡𝑚)φ(λ(m))/m=exp⁡(−(1+o(1))log⁡log⁡mlog⁡log⁡log⁡m).其中,指数部分系数中的 𝑜(1)o(1) 吸收了因子 𝜑(𝜆(𝑚))/𝜆(𝑚)φ(λ(m))/λ(m) 的贡献.故而,𝜆λ‑原根可以在期望 exp⁡((1+𝑜(1))log⁡log⁡𝑚log⁡log⁡log⁡𝑚)exp⁡((1+o(1))log⁡log⁡mlog⁡log⁡log⁡m) 次内找到.关于欧拉函数的估计,可以参考论文 Rosser, J. Barkley, and Lowell Schoenfeld. "Approximate formulas for some functions of prime numbers." Illinois Journal of Mathematics 6, no. 1 (1962): 64-94.关于 Carmichael 函数的估计,可以参考论文 Erdos, Paul, Carl Pomerance, and Eric Schmutz. "Carmichael’s lambda function." Acta Arith 58, no. 4 (1991): 363-385. ↩
  1. 原始论文参见 Adleman, Leonard, Kenneth Manders, and Gary Miller. "On taking roots in finite fields." In 18th Annual Symposium on Foundations of Computer Science (sfcs 1977), pp. 175-178. IEEE Computer Society, 1977.一个更易读的介绍可见于 Cao, Zhengjun, Qian Sha, and Xiao Fan. "Adleman-Manders-Miller root extraction method revisited." In International Conference on Information Security and Cryptology, pp. 77-85. Berlin, Heidelberg: Springer Berlin Heidelberg, 2011. ↩
  1. 由于这一算法要求 𝑘k 是素数,所以最差情形中,它需要对 𝜑(𝑚)φ(m) 的最大素因子 𝑝p 求 𝑎a 模 𝑚m 的 𝑝p 次方根.这一过程中,需要对 𝑝p 次本原单位根求 𝑎a 模 𝑚m 的离散对数.即使应用 BSGS 算法,这一过程也需要 𝑂(√𝑝)O(p) 时间.但是,论文 Fouvry, Étienne. "Theoreme de Brun-Titchmarsh; application au theoreme de Fermat." Inventiones mathematicae 79, no. 2 (1985): 383-407 指出,存在正密度的素数 𝑚m,使得 𝜑(𝑚) =𝑚 −1φ(m)=m−1 的最大素因子 𝑝 =Ω(𝑚2/3)p=Ω(m2/3).这意味着这一算法的复杂度至少为 Ω(𝑚1/3)Ω(m1/3),劣于文中介绍的改良 Tonelli–Shanks 算法. ↩
本页面最近更新: 2026/1/7 08:56:54,更新历史 发现错误?想一起完善?在 GitHub 上编辑此页! 本页面贡献者:Great-designer, Tiphereth-A, c-forrest, ChungZH, iamtwz, Xeonacid 本页面的全部内容在CC BY-SA 4.0SATA 协议之条款下提供,附加条款亦可能应用