Processing math: 100%

任意类型多项式乘法

前言

所谓“任意类型”,事实上指的是一种代数结构 A=(D,+,),满足:

  • +:D×DD,且 (D,+) 构成阿贝尔群。
  • :D×DD
  • (u+v)(x+y)=ux+uy+vx+vy

即,元素集合 D 上定义了加法和乘法,加法满足交换律,乘法不需要满足结合律,满足分配律。也就是说,A 是不需要满足乘法结合律的环。

于是,我们有一种算法,可以计算 A[x] 上的乘法。

在实际应用中,A 可以是几乎任何你能想到的东西:模 998244353,模 19260817,模 264,也可以是矩阵甚至是四元数,或者你自己随便定义的东西。

前置知识

定义与记号

我们会用到抽象代数中的一些概念,但是我们不需要知道严谨的定义,只需要一个相对感性的理解即可。

  • 环(Ring)是由元素集合、加法运算、乘法运算组成的三元组 (D,+,),加法满足交换律,乘法满足分配律,加法和乘法满足结合律。事实上,在本文探讨的范围中,乘法结合律并不重要,所以乘法不满足结合律我们也将其视作环。
  • 给定环 A,那么 A[x] 指系数是 A 中元素的关于 x 的多项式构成的环。
  • 给定环 A 以及 dA,那么 A/dA 中元素在“模 d”意义下运算构成的环。你不需要了解这里“模”的严谨定义,因为在本文中只会涉及多项式的取模,这是大家熟知的。
  • 对于 nN, xA,我们记 nxnx 相加。

单位根

因为抽象的概念难以描述,所以我们将在复数域上讨论单位根。

ωC 满足 ωn=1,那么称其为 n 次单位根

若对于  1k<n:ωn1,那么称 ω 为一个 n 次本原单位根(Primitive Root),或称原根。我们任取一个本原单位根,记作 ωn。那么任何一个单位根都是 ωn 的幂。

ω=ωnk,那么可以发现,ω 是原根当且仅当 gcd(k,n)=1。于是我们可以得到:原根的数量是 φ(n)

分圆多项式

定义 n 阶分圆多项式 Φn(x)=gcd(k,n)=1(xωnk)。即,根恰好为 φ(n) 个原根的多项式。

那么我们有结论:

  • Φn(x) 次数为 φ(n),这是显然的。

  • Φn(x)(xn1),证明:

    因为 (xn1) 的根是所有 n 次单位根,所以 Φn(x) 的所有根都是 (xn1) 的根,将多项式分解即得证。

  • xn1=d|nΦd(x),证明:

    Pdd 次原根组成的集合。记 g=gcd(n,k),那么,ωnk=ωn/gk/g, gcd(n/g,k/g)=1,于是每个 n 次单位根恰好在 Pn/g 中出现一次。于是结论可以得证。

  • Φn(x) 是首一整系数多项式,证明:

    首一显然,整系数考虑使用数学归纳。

    • 对于 n=1 显然成立。

    • 假设结论对于所有 m<n 均成立。那么,令

      g(x)=d|n,d<nΦd(x)

      则根据归纳假设知 g(x) 是整系数的。于是根据带余除法,有唯一的 q(x),r(x) 满足:

      xn1=g(x)q(x)+r(x)

      q(x) 是整系数的。根据上一个结论,我们有 xn1=Φn(x)g(x),所以:

      r(x)=(Φn(x)q(x))g(x)

      根据带余除法性质,degr(x)<degq(x),所以 Φn(x)q(x)=0。所以 Φn(x) 是整系数的。

    于是结论得证。

  • Φn(x) 是不可约的,证略。

  • 对于 n 次原根 ωn,关于 ωn 的多项式的运算可以对 Φn(ωn) 取模,证明:

    因为 Φn(ωn)=0,所以取模不会影响多项式的实际值。

    该结论的一个引申结论是,ωnk 可以被唯一地被 ωn0,ωn1,,ωnφ(n)1 线性表示,并且系数为整数。

Cantor's Algorithm

要进行多项式乘法,我们尝试使用 DFT。那么我们主要面对的问题有两个:

  1. 不存在单位根。
  2. IDFT 需要进行除法(即由 nx,n 推出 x),我们不一定能够做除法。

接下来我们尝试逐个解决这两个问题。

规避单位根

我们采用扩域的思想,引入虚单位根 ωn 并且带着它做运算。但是这样做一次乘法复杂度就会达到 O(n2),肯定是无法接受的。所以我们有了下面的算法。

递归计算卷积

假设我们要求 A(x)B(x),那么我们选取最小的 m=sr 满足 φ(m)>degA+degB

那么我们可以将问题转化为求 A(x)B(x)modΦm(x),也就是求 A(ωm)B(ωm)。因为 φ(m)>degA+degB,所以结果的指数不会溢出。又因为 ωmk 能被 ωm0,ωm1,,ωmφ(m)1 线性表示,所以得到的结果唯一(如果对 xm1 取模,就可能得到不同的实际相等的结果)。那么最终 ωmk 的系数就是 xk 的系数。

Im=A[ωm]/Φm(ωm),然后写下我们的算法形式:

算法形式:给定 A(ωm),B(ωm),m,在 Im 上计算 A(ωm)B(ωm)

p=su,q=sv 满足 u+v=r, v+1uv+2,那么我们可以将多项式重写:

A(x)=j=0q1(i=0p1aiq+jxiq)xj=j=0q1(i=0p1aiq+jωmiq)xj=j=0q1(i=0p1aiq+jωpi)xj

那么,xj 的每一项系数都是 Ip 中的元素,于是我们的问题转化成了,求 Ip[x] 上的乘法。

我们可以做 Ip[x] 上长度为 sq 的 DFT 来求出这个结果,这个 DFT 具体怎么在下一段说。我们做完 DFT 后,需要将两个数组对应位置相乘,每个位置都是 Ip 中元素。这个问题符合我们的算法形式,所以可以直接递归求解。求出结果后带入 xωm 即可得到答案。

m 足够小的时候可以进行暴力卷积,可以认为是进行 O(1) 次乘法。

Ip 上的 DFT

在这里,我们假设我们可以进行除法。

回忆一下 DFT 的过程,以 s=2 为例(其它 s 类似):

F(ωnk)=F0(ωn/2k)+ωnkF1(ωn/2k)F(ωnk+n/2)=F0(ωn/2k)ωnkF1(ωn/2k)

因为 nq<p/s,所以我们可以进行转化:ωn=ωpp/n。我们需要进行的操作是 Ip 上的加法以及乘 ωpk,其中后者可以看做是循环移位。于是两个操作都可以 O(p) 完成。那么一次 DFT 需要进行 O(srpq) 次加法。

s>2 的时候,蝴蝶变换会变得十分鬼畜,可以采用转置 FFT 的技巧省略蝴蝶变换。

时间复杂度

我们不妨把 s 看做常数,那么一层中 DFT 的复杂度是 O(mlogm)

因为 p,q 都是 O(m) 的,所以我们可以得到:

  • 加法次数:T(m)=O(m)T(m)+O(mlogm)=O(mlogmloglogm)
  • 乘法次数:T(m)=O(m)T(m)+O(1)=O(n)

规避除法

假设我们要做长度为 n=sr 的 DFT,且有 ns 次单位根 ωns

设我们要求 C(x)=A(x)B(x),且 A,B,C 系数分别为 ai,bi,ci。记 D=DFT(a)DFT(b),设 di 为对 D 做 IDFT 后未除以 n 的结果,那么:

(1)di=n(ci+ci+n)

a^i=aiωnsi, b^i=biωnsi。记 E=DFT(a^)DFT(b^),然后设 eiωnsi 为对 E 做 IDFT 后未除以 n 的结果,那么:

(1)ehωnsh=n(chωnsh+ch+nωnsh+n)(2)eh=n(ch+ch+nωs)

(1),(2) 联立可以得到:

{n(1ωs)ch=ehdhωsn(1ωs)cn+h=dheh

τn=Φn(1),那么 τn 是一个整数,且当 n 为素数 p 的幂时 τn=p,否则 τn=1。则:

τs1ωs=2i<s,gcd(i,s)=1(1ωsi)

将上式乘上这个等式,得到:

{nτsci=(eidiωs)2i<s,gcd(i,s)=1(1ωsi)nτsci+n=(diei)2i<s,gcd(i,s)=1(1ωsi)

系数都是好求的,因此我们把式子简记为:

{M1ci=N1M2ci+n=N2

cici+n 过程类似,以前者为例。选择两个不同的互素的 s 进行上面的操作,我们可以得到 M1,1ciM1,2ci 的值。而 M1,1M1,2 互素,所以可以用 exgcd 求解 M1,1x+M1,2y=1。然后计算 xM1,1ci+yM1,2ci 的值就是 ci

这里使用的单位根可以直接用之前造出来的单位根,也就是在 Ip 上运算。

实现细节

  • 实际实现不需要一直对 Φm(x) 取模,可以在递归过程中对 xm1 取模(也就是循环卷积),最后再对 Φm(x) 取模。
  • 在实际应用中,如果 A 是模域 Fp,那么可以不用规避除法的步骤。对于 2p,可以选择 s=3;对于 2p,可以选择 s=2。这样 s 就存在逆元,可以直接除。
  • 对于 pP,有 Φpk(x)=i=0p1xipk1

参考资料

参考文献

参考代码

本文作者:ExplodingKonjac

本文链接:https://www.cnblogs.com/ExplodingKonjac/p/17904039.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   ExplodingKonjac  阅读(124)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· BotSharp + MCP 三步实现智能体开发
· BotSharp 5.0 MCP:迈向更开放的AI Agent框架
· 5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
· 【ESP32】两种模拟 USB 鼠标的方法
· 设计模式脉络
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起