Loading

快速傅里叶变换实用讲解

多项式模板实用讲解

再也不用担心 FFT 只能记板子了。


快速傅里叶变换

一个 \(n\) 项(\(n-1\) 次)多项式可以用 \(n\) 个点值表示,利用这一点我们可以实现系数表达与点值表达的转换。

对于二的整数次幂 \(n\) 项多项式 \(F(x)=\sum_{i=0}^{n-1}a_ix^i\),我们用求出点值 \(F(w_n^i)\) 其中 \(w_n\)\(n\) 次单位根。

\(F_0(x)=a_0+a_2x+a_4x^2+\cdots,F_1(x)=a_1+a_3x+a_5x^2\)

很明显有\(F(x)=F_0(x^2)+xF_1(x^2)\)

那么 \(\forall k< \frac n2\)

\[\begin{aligned} F(w_n^{k})&=F_0(w_n^{2k})+w_{n}^kF_1(w_n^{2k})\\ &=F_0(w_{\frac n2}^k)+w_{n}^kF_1(w_{\frac n2}^k)\\ F(w_n^{k+\frac n2})&=F_0(w_n^{2k+n})+w_{n}^{k+\frac n2}F_1(w_n^{2k+n})\\ &=F_0(w_{\frac n2}^k)-w_{n}^kF_1(w_{\frac n2}^k)\\ \end{aligned} \]

可以发现这两个仅是符号的差别,于是我们可以分治解决。


快速傅里叶逆变换

根据系数求点值可以看作一个线性变换,即:

\[\begin{bmatrix} 1&w_n&w_n^2&\cdots&w_n^{n-1}\\ 1&w_n^2&w_n^4&\cdots&w_n^{2(n-1)}\\ 1&w_n^3&w_n^6&\cdots&w_n^{3(n-1)}\\ \vdots&\vdots&\vdots&\ddots&w_n^{3(n-1)}\\ 1&w_n^{n-1}&w_n^{2(n-1)}&\cdots&w_n^{(n-1)^2}\\ \end{bmatrix} \begin{bmatrix} f_0\\ f_1\\ f_2\\ \vdots\\ f_{n-1}\\ \end{bmatrix} \]

逆变换相当于对这个矩阵求逆,得到(我并不会证明):

\[\frac 1{n}\begin{bmatrix} 1&\frac1{w_n}&\frac1{w_n}^2&\cdots&\frac1{w_n}^{n-1}\\ 1&\frac1{w_n}^2&\frac1{w_n}^4&\cdots&\frac1{w_n}^{2(n-1)}\\ 1&\frac1{w_n}^3&\frac1{w_n}^6&\cdots&\frac1{w_n}^{3(n-1)}\\ \vdots&\vdots&\vdots&\ddots&\frac1w_{n}^{3(n-1)}\\ 1&\frac1{w_n}^{n-1}&\frac1{w_n}^{2(n-1)}&\cdots&\frac1{w_n}^{(n-1)^2}\\ \end{bmatrix} \]

该有的性质还是有,直接用 FFT 的方法求解即可。


蝶形变换

好美的名字。

直接给结论吧:最终系数 \(a_i\) 会跑到 \(rev_i\) 的位置,其中 \(rev_i\) 指将 \(i\) 二进制表示翻转后的结果。

证明也十分简单,考虑上述分治过程,分治到第 \(k\) 次本质在决定位置的二进制第 \(k\) 高位,而我们考虑的确是二进制第 \(k\) 低位,就相当于将其二进制翻转。

于是我们就改递归为递推了。


模意义

单位根是复数域上的概念,对应在模意义域就是原根。

其实上述分治过程只是用到了单位根的三个性质:

  • \(w_n^n=1\)

  • \(w_n^{\frac n2}=-1\)

  • \(w_{n}^{2k}=w_{\frac n2}^k\)

而原根也有这些性质,可以放心使用。

但还有一点,由于 \(w_n=G^{\frac {P-1}n}\),其中 \(G\) 表示原根,\(P\) 表示模数,这里要求 \(P-1\)\(n\) 的倍数,即至少有 \(\log_2 n\)\(2\) 的因子。

常用的的有:

  • \(P=998244353,G=3\)

  • \(P=469762049,G=3\)

  • \(P=1004535809,G=3\)


任意模数

很简单,分别用上文的三种模数实现 NTT 后用中国剩余定理还原出真实的值,从而实现任意模数。


求导推式子

当遇到形如 \(f'(x)=f(x)+g(x)\) 的式子时,若 \(g(x)\) 已知,则可以 \(\mathcal O(n)\) 求得 \(f(x)\)\(n\)


动态多项式乘法

每次乘/除上一个因式,动态维护其结果

多项式乘法可以看作一个递推,那么多项式除法就是一个逆过程,在这之上易于计算。

当每次乘除的因式极短时,这种方法要优于FFT。


生成函数的上下界限制

生成函数,在多项式形式的上下界进行修改,其实是限制了方案。


多项式求导

直接根据定义算得:\(\sum_{i}(i+1)a_{i+1}x^i\)

多项式积分

直接根据定义算得:\(\sum_{i=1}\frac{a_{i-1}}ix^i+C\)


牛顿迭代法

  • 求解方程 \(f(x)=0\) 的解。

方法:取一点 \(x_0\),求切线方程 \(f'(x_0)(x-x_0)+f(x_0)=0\),得到 \(x=x_0-\frac{f(x_0)}{f'(x_0)}\)。这样精度每次会平方提升。

  • 求解形式幂级数方程 \(F(B(x))=0\) 的解。

和上述方法类似,迭代得 \(B_{k+1}=B_k-\frac{F(B)}{F'(B)}\)

这里给出精度平方级提升的证明:
设准确解为 \(B_*\),即 \(F(B_*)=0\),设误差 \(E_k=B_k-B_*\),现在证明,如果 \(E_k\equiv 0\pmod {x^m}\),则 \(E_{k+1}\equiv 0\pmod{x^{2m}}\)

\(F(B_k),F'(B_k)\) 泰勒展开:

\[F(B_k) = F(B_* + E_k) = \underbrace{F(B_*)}_{=0} + F'(B_*)E_k + F''(B_*)E_k^2 + O(E_k^3)\\ F'(B_k) = F'(B_* + E_k) =F'(B_*) + F''(B_*)E_k + O(E_k^2)\\ \]

因为 \(E_k\equiv 0\pmod {x^m}\),所以 \(O(E_k^3)\equiv O(E_k^2)\equiv 0\pmod {x^{2m}}\)

所以 \(\frac{F(B_k)}{F'(B_k)}\equiv \frac{F'(B_*)E_k + F''(B_*)E_k^2}{F'(B_*) + F''(B_*)E_k}=E_k\pmod{x^{2m}}\)

所以 \(B_{k+1}\equiv B_{k}-E_k=B_*\pmod{x^{2m}}\)


多项式求逆

注:为了美观,本段所有多项式省去 \((x)\)
假设我们求出了 \(\frac 1{F}\equiv H\pmod {x^{\frac n2}}\),现在要求 \(\frac 1{F}\equiv G\pmod {x^n}\)

显然我们有 \(H-G\equiv 0\pmod{x^{\frac n2}}\),考虑对左边平方,令\(P=H-G\),则\([x^i]P^2=\sum_{j}[x^j]P*[x^{i-j}]P\),而 \(\min\{j,i-j\}<\frac n2\),所以 \([x^j]P\)\([x^{i-j}]P\) 一定有一个为 \(0\),所以 \(P^2\equiv 0\pmod {x^n}\)

所以 \(H^2-2H\cdot G+G^2\equiv 0\pmod {x^n}\),同乘 \(F\) 后移项得到 \(G\equiv 2H-H^2F\pmod{x^n}\)

因为 \(T(n)=T(\frac n2)+\mathcal O(n\log n)\)。最后复杂度 \(\mathcal O(n\log n)\)

所以多项式求逆要求常数项不为 \(0\)

也可以直接牛顿迭代,求解 \(F(B)=A\times B-1=0\)

\[\begin{aligned} B_{k+1}&\equiv B_k-\frac{A\times B_k-1}{A}\pmod{x^{2^k+1}}\\ &\equiv B_k(2-A\times B_k)\pmod{x^{2^k+1}} \end{aligned} \]

注意这里分母的 \(A\) 不能和分子的 \(A\) 消掉,因为多项式除法就是根据多项式求逆定义的,而我们还在对 \(A\) 求逆,所以除法不存在。

这里应该理解为:

\[\frac{F(B_k)}{F'(B_k)}\equiv F(B_k)B_k\pmod{2^{k+1}} \]

精度成立是因为:

\[F(B_k)\equiv 0\pmod {x^{2^k}}\\ \frac 1{A}\equiv B_k\pmod {x^{2^k}} \]

结合之前的证明方法易得。

为了保证复杂度,\(A\) 每次应该取 \(\bmod x^{2^{k+1}}\) 的结果计算。


分治FFT

半在线卷积的解法,其实就是CDQ分治优化DP+FFT。

虽然模板题可以多项式求逆搞过去。但只需要加一个逐项系数 \(a_i\),即变为:

\[f_i=a_i\sum_{j=1}^if_{i-j}g_j \]

就可以阻止多项式求逆。


多项式对数函数ln

先求导,再积分:

\[\ln F=\int \frac {F'}Fdx+\ln f_0 \]

证明:在模意义下仅当 \(f_0=1\) 时有意义。

因为当 \(f_0\ne 1\) 时,\(\ln f_0\notin \mathbb F_p\)

这是因为 \(e\) 是一个超越数,不存在 \(n>1\) 使得 \(e\)\(F(x)=x^n-f_0\) 的解。


多项式指数函数exp

由ln的证明可知,仅当 \(f_0=0\) 是模意义下有意义。

做法一:先求导再积分,半在线卷积,双log

\(G=\exp F\)

对两边求导得:\(G'=G\times F'\)

积分得 :\(G=\int G\times F'\)

则可以写作 \(g_n=\frac 1n\sum_{i=0}^{n-1}g_if_{n-1-i}\)

半在线卷积即可。

做法二:

\(B=e^A\),写作 \(F(B)=\ln B-A=0,F'(B)=B^{-1}\)

迭代式为:

\[B_{k+1}\equiv B_k(1+A-\ln B_k)\pmod{2^{k+1}} \]

牛顿迭代即可。


多项式幂函数

\(F^k(x)\),首先如果 \(f_0=1\),则直接 \(\exp(k\ln F)\)

否则找到最小的 \(t\) 使得 \(f_t\ne 0\),有:

\[F^k(x)=(\frac{F(x)}{a_tx^t})^ka_t^kx^{tk} \]

把常数项系数化为 \(1\) 来做。
关于 k 如何取模的问题 :

结论,模 \(P\) 意义下:

\[F^P(x)\equiv f_0^P\mod{x^n}(n<P) \]

证明:

根据多项式定理:

\[F(x)^P = \left( \sum_{i=0}^m a_i x^i \right)^P = \sum_{\substack{k_0 + k_1 + \cdots + k_m = P \\ k_i \geq 0}} \binom{P}{k_0, k_1, \ldots, k_m} \prod_{i=0}^m (a_i x^i)^{k_i} \]

如果 \(\forall k_i<P\),则此系数一定可以被 \(P\) 整除,最终变为 \(0\)

所以当且仅当存在某个 \(i\) 使得 \(k_i = P\) 且其他所有 \(k_j = 0\)\(j \neq i\)),则

\[\binom{P}{0, \ldots, 0, P, 0, \ldots, 0} = \frac{P!}{P! \prod_{j \neq i} 0!} =1 \]

此时对应项为 \(a_i^P x^{iP}\)

而当 \(i>0\)\(iP>n\),被截断,只有 \(i=0\) 时会被计算,所以原命题成立。

而这道题转换后常数项为 \(1\),代入结论有:

\[F^P(x)\equiv 1\pmod{x^n} \]

所以这里的 \(k\) 应该直接对 \(P\) 取模,而计算 \(a_t^k\) 时,应该根据费马小定理将 \(k\)\(P-1\) 取模。


多项式平移

给定 \(F(x)\),求 \(F(x+c)\)

\[\begin{aligned} F(x+c)&=\sum_if_i(x+c)^i\\ &=\sum_jx^j\sum_{i=j}^nf_i{i\choose j}c^{i-j}\\ &=\sum_jx^j\frac1{j!}\sum_{i=j}^nf_ii!\frac{c^{i-j}}{(i-j)!}\\ \end{aligned} \]

最后式子很像卷积,但不是,因为其是差而非和为定值。

所以设 \(g_{-i}=\frac{c^i}{i!},h_i=f_ii!\)

\(F(x+c)=\sum_i\frac{x^i}{i!}[x^j]G(x)H(x)\)

具体实现就是把 \(G(x)\) 先向右平移 \(n\) (乘上 \(x^n\) )把非零项下标变为正的,最后再左移 \(n\) 位(除以 \(x^n\))即可。


多项式插值

\(f(X)=\sum_{i}y_i\prod_{j\ne i}\frac{X-x_j}{x_i-x_j}\)


多项式点值平移

给点值 \(f(0)\sim f(n)\),求 \(f(m)\sim f(n+m)\)

\[\begin{aligned} f(x)&=\sum_{i=0}^nf(i)\sum_{j\ne i,0\le j\le n}\frac{x-j}{i-j}\\ &=\sum_{i=0}^nf(i)\frac{x!}{(x-1-n)!(x-i)i!(n-i)!(-1)^{n-i}}\\ &=\frac{x!}{(x-1-n)!}\sum_{i=0}^n\frac{1}{x-i}\frac{f(i)(-1)^{n-i}}{i!(n-i)!} \end{aligned} \]

\(a_i=\frac{(-1)^{n-i}f(i)}{(n-i)!i!}[i\le n]\)\(b_i=\frac{1}{i+m-n}\)

\[\begin{aligned} f(x)&=\frac{x!}{(x-1-n)!}\sum_{i}b_{x-m+n-i}a_i \\&=\frac{x!}{(x-1-n)!}[z^{x-m+n}]A(z)B(z) \\&=x^{\underline {n+1}}[z^{x-m+n}]A(z)B(z) \end{aligned} \]

复杂度 \(\mathcal O(n\log n)\)

如果设作 \(b_i=\frac1i\),复杂度就是 \(\mathcal O(m\log m)\),而 \(m\) 不是输入规模,可以非常大。


多项式带余除法

\(F\) 次数为 \(n\)\(Q\) 次数为 \(m\),求 \(F(x)=G(x)Q(x)+R(x)\)\(Q\)\(n-m\) 次多项式,\(R\)\(m-1\) 次多项式。

考虑一种操作

\[A_R(x)=x^nA_R(\frac 1x) \]

可以发现 \(A_R[i]=A[n-i]\),然后开始推式子:

\[\begin{aligned} F(x) &= Q(x) \cdot G(x) + R(x)\\ F\left(\frac{1}{x}\right) &= Q\left(\frac{1}{x}\right) \cdot G\left(\frac{1}{x}\right) + R\left(\frac{1}{x}\right)\\ x^n F\left(\frac{1}{x}\right) &= x^{n-m} Q\left(\frac{1}{x}\right) \cdot x^m G\left(\frac{1}{x}\right) + x^{n-m+1} \cdot x^{m-1} R\left(\frac{1}{x}\right)\\ F_R(x) &= Q_R(x) \cdot G_R(x) + x^{n-m+1} \cdot R_R(x)\\ F_R(x) &\equiv Q_R(x) \cdot G_R(x) \pmod{x^{n-m+1}}\\ Q_R(x) &\equiv \frac{F_R(x)}{G_R^{-1}(x)} \pmod{x^{n-m+1}} \end{aligned} \]

求出 \(Q\) 后可以接着求出 \(R\)


实用等式

基本等式

\[e^{cx}=\sum_i\frac{(cx)^i}{i!}\\ \frac{1}{1-cx}=\sum_i(cx)^i \]

前缀和,差分变换:

\[\frac1{1-x}A(x)=\sum_i(\sum_{j=0}^ia_i)x^i\\ ({1-x})A(x)=a_0+\sum_{i=1}(a_i-a_{i-1})x^i\\ \]

倒数对数公式

\[\ln \frac1{1-x}=\sum_{i=1}\frac{x^i}i \]

posted @ 2025-02-24 17:54  lupengheyyds  阅读(88)  评论(0)    收藏  举报