FFT/FNTT 算法笔记

FFT/FNTT 算法笔记

1.前置知识

1.1多项式

多项式

\[A(x)=\sum_{j=0}^{n-1}a_jx^j \]

多项式乘法

\(C(x)=A(x)*B(x)\)

\[c_j=\sum_{k=0}^ja_jb_{j-k} \]

多项式的系数表示

\[(a_0,a_1,...,a_{n-1}) \]

多项式的点值表示

\[((x_0,y_0),(x_1,y_1),...,(x_{n-1},y_{n-1})),y_i=A(x_i) \]

多项式求值

从系数表示确定点值表示

多项式的插值

从点值表示确定系数表示

1.2单位根

\(n\) 次单位根

\[w_n=e^{i(2\pi/n)} \]

\[w_n^n=1,w_n^{n/2}=-1 \]

引理 1:

\[w_{dn}^{dk}=w_n^k \]

引理 2:

\[如果 n>0 且 n 是偶数,则 \{w_n^{2i}|0\leq i<n\}=\{w_{n/2}|0\leq i<n/2\}\]

引理 3:

\[如果 n>0 且 n 不整除非负整数 k\\ \sum_{j=0}^{n-1}w_n^{kj}=0\]

1.3原根

首先取一个特殊的模数 \(p=qn+1,n=2^k,k尽可能大\)

\[998244353=7\times 17 \times 2^{23}+1,g=3\]

\(n\) 次单位根

\[g_n=g^{(p-1)/n} \]

\[g_n^n=(g^q)^n=g^{qn}=g^{p-1}=1 \]

\[(g_n^{n/2})^2=1 \]

\(g_n^{n/2}=1\)\(g^{(p-1)/2}=1\)违反原根性质,舍去

\[g_n^{n/2}=-1 \]

引理 1:

\[g_{dn}^{dk}=(g^{(p-1)/(dn)})^{dk}=(g^{(p-1)/n})^k=g_n^k \]

引理 2:

\[如果 n>0 且 n 是偶数,则 \{g_n^{2i}|0\leq i<n\}=\{g_{n/2}^i|0\leq i<n/2\}\]

引理 3:

\[如果 n>0 且 n 不整除非负整数 k\\ \sum_{j=0}^{n-1}g_n^{kj}=\frac{1-g_n^{jn}}{1-g_n^j}=0\]

2 递归 FFT

FFT 是多项式求值和插值的一种 \(\Theta(n \log n)\) 算法。

首先假设 \(n=2^k\)

然后根据下标二进制表示的末位是 1 还是 0 分成两个多项式

\[A_0(x)=a_0+a_2x+a_4x^2+...a_{n-2}x^{n/2-1}\\ A_1(x)=a_1+a_3x+a_5x^2+...a_{n-1}x^{n/2-1}\\ A=A_0(x^2)+xA_1(x^2) \quad (2.1)\]

那么在FFT中递归做这两个子问题 \(A_0,A_1\),边界是 \(n=1\)

根据引理2,可以把单位根的规模从 \(n\) 缩小到 \(n/2\)

然后在主函数中处理:

\[A(w_n^k)=A_0(w_n^{2k})+w_n^kA_1(w_n^{2k}) \quad (2.1)\\ =A_0(w_{n/2}^k)+w_{n}^kA_1(w_{n/2}^k)\]

对于 \(k<n/2\)

直接按照式子转移

对于 \(k>n/2\)

\(w_n^k=-w_n^{k-n/2}\) 然后转移

对于插值过程只需要找到范德蒙德矩阵的逆矩阵即可

具体详见《算法导论》,这里给出结论:将 \(-w_n^k/n\) 代替 \(w_n^k\) 带入即可

关于时间复杂度 \(T(n)=2T(n/2)+\Theta(n)=\Theta(n \log n)\)

3 非递归 FFT

一种原地优化的FFT,时空码三方面好于递归版。

注意到代码中这一段

\( for\ k=0 \ to \ n/2-1\\ \qquad y_k = y0_k+w_n^k\,y1_k\\ \qquad y_{k+n/2} = y0_k-w_n^k\,y1_k\\ \)

这里只使用到了 \(y0_k,y1_k,y_k,y_{k+n/2}\) 这些值,于是考虑对他们进行原地变换(蝴蝶操作)。

那么这需要确定递归到最底层的顺序,然后循环操作,从下往上,就可以实现非递归FFT了。注意这里的蝴蝶操作需要设置一个临时变量。

接下来确定递归到最底层的顺序。

[000 001 010 011 100 101 110 111]
[000 010 100 110] [001 011 101 111]
[000 100] [010 110] [001 101] [011 111]
[000] [100] [010] [110] [001] [101] [011] [111]

规律是一个位置递归到最底层,就是它的二进制位翻转所对应的位置。设\(n=2^s\),因为对于某一个递归深度 \(t\)。这时候这些位置的前 \(t-1\) 位都相同。\(t\) 位为0的书到达左侧,而这些位置,正好他们的 \(s-1-t\) 位都是0。反之,1的情况同理。所以这个规律成立。

这个不过是常数优化。

4 FNTT(整数FFT)

如果FFT里全是整数,如何防止掉精度呢?

尝试对某个数取模(模数最好大于它乘完得到的数),使用原根替换单位根。

观察引理是否仍然成立,在第一章已经做过说明

所以可以使用原根替换单位根,然后一切照旧。

5 分治 FFT

推荐阅读:
ABC213H Editorial
P4721

对于后面依赖前面的dp转移,使用cdq分治的思想递归掉前面,然后卷积前面转移到后面,再递归到后面。

代码实现 ABC2113H

posted @ 2024-06-10 10:56  妖灵梦  阅读(103)  评论(0)    收藏  举报