任意模数 NTT

给定一个 nn 次多项式 AA 和一个 mm 次多项式 BB,计算 A×BA \times B,系数对 pp 取模。

n,m105n,m \le 10^5

做法

A0i=AiM,A1i=AimodMB0i=BiM,B1i=BimodM\begin{aligned} A0_i=\lfloor \frac {A_i}M \rfloor,A1_i=A_i \bmod M\\ B0_i=\lfloor \frac {B_i}M \rfloor,B1_i=B_i \bmod M \end{aligned}

于是

A=MA0+A1B=MB0+B1\begin{aligned} A = M \cdot A0 + A1\\ B = M \cdot B0 + B1 \end{aligned}

进一步

A×B=M2A0B0+M(A0B1+A1B0)+A1B1A \times B = M^2 \cdot A0 \cdot B0 + M(A0 \cdot B1 + A1 \cdot B0) + A1 \cdot B1

先对 A0,A1,B0,B1A0,A1,B0,B1 做一遍 DFT,求出 A0×B0,A0×B1+A1×B0,A1×B1A0 \times B0, A0 \times B1 + A1 \times B0,A1 \times B1 的点值表示后再分别 IDFT,共 77 次。

注意系数可能达到 101410^{14},需要用 wnk=cos2kπn+isin2kπnw_n^k=\cos \frac {2k\pi}n+i \cdot \sin \frac {2k\pi}nwnkw_n^k 进行预处理保证精度。

优化

下面考虑这样两件事:

  • 现在要对实系数多项式 A,BA,B 进行 DFT。

    我们定义

    P=A+iBQ=AiB\begin{aligned} P = A + iB\\ Q = A - iB \end{aligned}

    推导可以得到一个很优美的结论:

    conj(Q(wnk))=P(conj(wnk))\text {conj}(Q(w_n^k))=P(\text{conj}({w_n^{k}}))

    于是只需一次 DFT 就可以求出 A,BA,B 的点值表示。

  • 现在已知实系数多项式 A,BA,B 的点值表示 A,BA',B',要求 A,BA,B

    我们定义

    P=A+iBP = A' + iB'

    PP 进行 IDFT 得到 PP',于是

    P=A+iBP' = A + iB

    因此 PP' 的实数部分就是 AA, 虚数部分就是 BB

    于是只需一次 IDFT 就可以达到对 A,BA',B' 分别做 IDFT 的效果.

77 次 DFT 两两配对可以合并成 44 次 DFT。

代码

参考资料

国家集训队 2016 论文集,《再探快速傅里叶变换》毛啸。