【模板】分治 FFT

Link

Solution

有两种解法。

法1:

 直接上分治FFT,也就是CDQ分治+FFT。

 具体做法是先递归左半边,算出左半边答案之后,将左半边贡献到右半边,然后递归右半边。

 分治是一个log的,每次暴力计算贡献是\(\text O(n^2)\)的,考虑用FFT优化计算贡献的过程。总复杂度变成\(\text O(n{log_n}^2)\)。

 需要注意:因为只算左半边对右半边的贡献,所以f数组右半边应置为0。

法2:

 设 \(F(x)=\sum\limits_{i=0}^{\infty}f[i]x^i\),\(G(x)=\sum\limits_{i=0}^{\infty}g[i]x^i\),并补充\(g[0]=0\),有
\[ \begin{align} F(x)*G(x)&=\sum\limits_{i=0}^\infty \sum\limits_{j=0}^\infty f[i]g[j]\cdot x^{i+j}\\ &=\sum\limits_{k=0}^\infty \sum\limits_{i=0}^k f[i]g[k-i]\cdot x^k &=\sum\limits_{k=0}^\infty \sum\limits_{i=0}^{k-1} f[i]g[k-i]\cdot x^k \end{align} \]
 当k=0是有\(\sum\limits_{i=0}^{k-1} f[i]g[k-i]\cdot x^k=0\)

 当k>0时有 \(\sum\limits_{i=0}^{k-1} f[i]g[k-i]\cdot x^k=f[k]\cdot x^k\)

 所以\(F(x)\)与\(F(x)*G(x)\)只差了一个常数项\(f[0]\)

即 \(F(x)=F(x)*G(x)+f[0]\) \(\Rightarrow\) \(F(x)=\frac{f[0]}{1-G(x)}=\frac{1}{1-G(x)}\)

 多项式求逆即可。

 这次重写发现自己NTT又有几个地方记不太清了:

  1.数组范围应该是2N向上取2的次幂,因为两个长度是N的多项式相乘有2N项

  2.for循环模拟递归过程,要注意是每一层操作相同且独立,所以不要把算单位根放在枚举每段起始位置p的那一层for了,应该放到最里层。

  3.根据实际情况(mod x的多少次方)判断长度。

  4.辅助数组用完记得清空。

上一篇:Matlab计算自相关和互相关


下一篇:【公式编辑测试】两类斯特林数的对偶