FFT/NTT 学习笔记
0. 前置芝士
- 基础群论
- 复数
\(\mathbb C = \mathbb R[x^2+1]\)
则有 \(i^2+1=(-i)^2+1=0\),\(i \in \mathbb C - \mathbb R\)
\(i^0=1;i^1=i;i^2=-1;i^3=-i;i^x=i^{x \bmod 4}(x \in \mathbb Z)\)
定理 0.1(欧拉公式)
\(e^{ik} = \cos k + i \sin k\)
证明:
(因为这里辛辛苦苦打出来的 \(\sf \LaTeX\) 炸了,所以放了个图,不是贺的)
定义 0.2(单位根)
\(\omega_k := e^{\frac{2\pi i}k}\) - 一些仅在本文生效的定义:
给定一个多项式 \(f(x)\) 和 \(i \le \deg f,f_i := \left\lfloor\dfrac f{x^i} \right\rfloor \bmod x\)。
本文中 \(f\) 和 \(f'\) 是两个函数,本文使用 \(\dfrac{{\rm d}f}{{\rm d}x}\) 表示导数。
1.引入
目标:求
\]
。
考虑取任意 \(\deg f + \deg g + 1\) 个复数 \(x_0,x_1,\dots,x_{\deg f + \deg g + 1}\),则有 \(h(x_i) = f(x_i)g(x_i)\),可以通过拉格朗日插值插回来(一般多项式题有 \(\deg f = \deg g\),且会 \(\bmod x^{\deg f+1}\),所以可以直接 \(x_0,x_1,\dots,x_{\deg f}\),之后的讲解以这种方法为主)
取 \(x_i = -\omega_{\deg f+1}^i\),则得到的 \(f(x_i) = \mathscr F f_i\)(此处 \(\mathscr F f\) 为长度为 \(\deg f+1\) 的序列而非多项式,且 \(\mathscr F f\) 的下标从 \(0\) 到 \(\deg f\))
插值部分不需要拉格朗日,有一个神奇的柿子:\(\mathscr{F}^{-1} f = \frac{1}{\deg f+1} \sum_{k=0}^{\deg f} { f}_k {\omega}^{k}_{\deg f}\)
构造方法见 IFFT
,但是建议把 \(\mathscr {F F}^{-1} f\) 展开看看正确性,这里就不推了
这两种东西被叫做 DFT 和 IDFT,根据定义式计算复杂度为 \(\mathcal O(n^2)\)
2.FFT
常数优化
定理 2.1 一个多项式 \(f(x)\) 一定能分成两部分 \(f(x)=O(x)+E(x)\),使得 \(\forall x E(x)=E(-x) \wedge \forall x O(x) = -O(-x)\)
构造性证明:\(E(x) = f_0x^0+f_2x^2+f_4x^4+\cdots,O(x)=f_1x^1+f_3x^3+f_5x^5+\cdots\)。
P.S. 通过麦克劳林展开式,可以得到 \(f(x)\) 不一定是多项式。
定理 2.2 \(\omega_n^x=-\omega_n^{x+\frac n2}\)
证明:\(e^{\frac{2\pi i}n \times (x+\frac n2)}=e^{\frac{2\pi i}n \times x+ \frac{2\pi i}n \times \frac n2}=e^{\frac{2\pi}n \times x} \times e^{\pi i} = -e^{\frac{2\pi}n \times x} = -\omega^x_n\)。
所以我们计算 DFT 和 IDFT 的时候可以考虑少搞一半。
(因为这个定理在 FFT 的过程中要反复进行,所以这里建议把 \(f\) 补全到 \(2^n\) 项)。分治(递归)
考虑分治地去完成 DFT。取代那一半的暴力运算,考虑变换出那一段:wait,一半的单位根和整个函数怎么变换?
定理 2.3 \((\omega_n^x)^2 = \omega_{\frac n2}^x\)
证明:\((\omega_n^x)^2 = (\omega_n^{2x}) = e^{\frac{2\pi i}n \times 2x} = e^{\frac{2\pi i}{n/2} \times x} = \omega_{\frac n2}^x\)
如果,我们跳出那思维呢?
设 \(E_f(x) = f_0x^0+f_2x^2+f_4x^4+\cdots,O_f(x)=f_1x^1+f_3x^3+f_5x^5+\cdots\)
令 \(E'_f(x) = E_f(\sqrt{x}); O'_f(x)=\dfrac {O_f(\sqrt{x})}{\sqrt{x}}\)
,则 \(2\deg E'_f-1 = 2\deg O'_f-1 = \deg f\)
有 \(f(x) = E'_f(x^2) + \omega_{2^n} O'_f(x^2)\)
当 \(x\) 是 \(2^n\) 次单位根的时候,\(x^2\) 一定是 \(2^{n-1}\) 次单位根,而正好 \(\deg E'_f = \deg O'_f = 2^{n-1}-1\),所以进行递归,把 \(E'_f\) 和 \(O'_f\) 进行 FFT,就可以完成了。
边界条件:\(n=0\),此时多项式变为一个常数,直接返回这个常数就可以了。分治(非递归)
这里因为正好 \(\deg f = 2^n-1\)(有 \(2^n\) 项),所以可以考虑使用位运算。
看看 \(E'_f\) 的每一项(\(O'_f\) 同理):
\(E'_f = f_0x^0 + f_2x^1 + f_4x^2 + f_6x^3 + \cdots + f_{2^n-2}x^{2^{n-1}-1}\)
发现都是二进制中第 \(0\) 位为 \(0\) 的数
我们把 \(E'_f\) 和 \(O'_f\) 合并相当于把两个 \(2^{n-1}\) 项的数组合并,这样我们 \(\tt DP\) 地去做,定义 \(f_{i,s,j}\) 代表将两个 \(2^{i-1}\) 项式合并,这两个区间是 \([s, s+2^{i-1})\) 和 \([s+2^{i-1},s+2^i)\) 合并后 \(\omega_{2^i}^{j-s}\) 的结果。
发现 \(s\) 的个数 \(\times\) \(2^i\) 的个数 是 \(O(n)\) 的,而 \(j\) 的个数是 \(O(2^i)\) 的,于是可以进行下一步复杂度分析复杂度分析
对于递归版:
\(T(n) = 2T(\dfrac n2)+O(n) = O(n \log n)\)
证明:\(T(n) = O(n) + 2T(\dfrac n2) = O(n) + O(n) + 4T(\dfrac n4) = \cdots(\text{这个递归会有 log n 层})\cdots = \sum\limits^{\log n}_{i=0} O(n) = O(n \log n)\)
对于递推版:
\(T(n) = \sum\limits_{i=1}^{\log n} \sum\limits_{s=1}^{\frac n{2^i}} O(2^i) = \sum\limits_{i=1}^{\log n} O(\dfrac n{2^i} \times 2^i) = \sum\limits_{i=1}^{\log n} O(n) = O(n \log n)\)
3.IFFT
- IDFT 公式推导
还记得我们在开篇提到的那个柿子吗:
\(\mathscr{F}^{-1} f = \frac{1}{\deg f+1} \sum_{k=0}^{\deg f} { f}_k {\omega}^{k}_{\deg f}\)
它的推导方法如下:
定义 \(\bar f(x) = \sum_{i} (\mathscr{F} f)_i x^i\)
然后再对 \(\bar f\) 做一次 DFT(lhx 内心吐槽:这方法是给人想的吗,个人感觉 \(\bar f\) 在数学上没什么实际意义,还来给 \(\bar f\) DFT?are you crazy???)
设 \(N = \deg f + 1\)(注意和 \(n = \log_2 (N)\) 做区别)
\(\bar f(\omega_N^x) = \sum\limits_{i=0}^{N-1} (\omega_N^{-xi} (\mathscr{F}f)_i) = \sum\limits_{i=0}^{N-1} (\omega_N^{-xi} \sum\limits_{j=0}^{N-1} f_j \omega_N^{ij})\),粗体部分由于负负得正。
因为 \(\omega_N^{-xi}\) 相对 \(\sum\limits_{j=0}^{N-1} f_j \omega_N^{ij}\) 是常数,所以可以乘进去,也就是 \(\sum\limits_{i=0}^{N-1} \sum\limits_{j=0}^{N-1} f_j \omega_N^{-xi} \omega_N^{ij} = \sum\limits_{i=0}^{N-1} \sum\limits_{j=0}^{N-1} f_j ( \omega_N^i)^{j-x}\)
交换两个 \(\sum\),并把 \(f_j\) 提出去,得到 \(\sum\limits_{j=0}^{N-1} \left ( f_j \sum\limits_{i=0}^{N-1} ( \omega_N^i)^{j-x} \right ) = \sum\limits_{j=0}^{N-1} \left ( f_j \sum\limits_{i=0}^{N-1} ( \omega_N^{j-x})^i \right )\)
这里 \(\sum\limits_{i=0}^{N-1} ( \omega_N^{j-x})^i\) 是一个等比数列,套用等比数列求和公式 得到 \(\dfrac{1 - \omega_N^{(j-x)N}}{1 - \omega_N^{j-x}} = \dfrac{1 - 1}{1 - \omega_N^{j-x}} = 0\),但是有一个条件,就是 \(\omega_N^{j-x} \ne 1\),如果 \(\omega_N^{j-x} = 1\),则答案为 \(n\),于是我们得到 \(\sum\limits_{j=0}^{N-1} [j \equiv x \pmod N]N \times f_j = f_x \times N\),于是我们得到一个离谱的结论:IFFT 就是先将单位根取倒数的 FFT。 - 实现
定理 1.1 \(\omega_N^a = \omega_N^{n \bmod N}\)
证明:\(\omega_N^a = \omega_N^{\lfloor a/N\rfloor N+a \bmod N}=\omega_N^{\lfloor a/N\rfloor N}\omega_{N}^{n \bmod N} = (\omega_N^N)^{\lfloor a/N\rfloor} \omega_{N}^{n \bmod N} = 1^{\lfloor a/N\rfloor} \omega_{N}^{n \bmod N} = \omega_{N}^{n \bmod N}\)
定理 1.2 \(\omega_N^{-a} = (\omega_N^{a})^{-1}\)
证明:\(\omega_N^{-a} = \omega_N^{(-a) \bmod N} = \omega_N^{N-a} = e^{i\pi\frac{2(N-a)}{N}} = e^{i\pi\frac{2N-2a}{N}} = e^{\frac{i\pi2N}{N}-\frac{i2\pi a}{N}} = e^{2\pi i} \div e^{2\pi i \times \frac aN} = (\omega_N^{a})^{-1}\)
于是我们可以通过 FFT 时 \(-a\) 改成 \(a\) 即可,或者说,\(Ia\),其中 \(I=-1\) 代表 FFT,\(I=1\) 代表 IFFT。 - 应用
\(O(n \log n)\) \(\bmod x^N\) 多项式乘除法:
因为点值表示法可以直积/直商,所以先对两个多项式FFT
,直积/直商后IFFT
回去就可以。
4.NTT
定义 \(\delta_p x(p \perp x) = \min\{i:x^i \bmod p = 1\}\)。
因为 \(x^{\varphi(p)} \bmod p=1(p \perp x)\),所以 \(\delta_p x \le \varphi(i)\)。
那么,有一些整数,满足 \(\delta_p x = \varphi(i)\),这种 \(x\) 就被称为是 \(p\) 的原根(可能不唯一)。
经常进行 NTT 的模数为 \(P=998244353=119 \cdot 2^{23}+1\),其原根为 \(g=3\)。
令 \(q = 119\),\(r = 23\),以下同余式若未标明模数默认为 \(P\)。
有 \(P-1=q2^r\),又因为长度经常为 \(N = \deg f+1 = 2^n\),所以两边除上一个 \(2^n\),得到 \(\dfrac {P-1}N = q2^{r-n}\)
令 \(q' = q2^{r-n}\),令 \(\rho_N \equiv g^{q'}\),发现 \(\omega_N\) 和 \(\rho_N\) 具有同样的性质,或者说 \(\langle \{0 \le i< n\mid\omega^i\},\times \rangle\) 和 \(\langle \{0 \le i < n\mid\omega^i\},\overset\bmod\times \rangle\) 这两个群同构。
Lemma 1: \(\rho_N^{i}\) 两两不同(证明:由于原根的性质,所以 \(\rho_N^i \equiv \rho_N^j \iff g^{q'i} \equiv g^{q'j} \iff q'i \equiv q'j \pmod {P-1} \iff (P-1) \mid q' (i-j)\)。
证明:构造双射 \(f(\omega_N^x) = \rho_N^x\),有 \(f(\omega_N^x) f(\omega_N^y) = \rho_N^x \times \rho_N^y = \rho^{(x+y) \bmod N} = f(\omega_N^{(x+y) \bmod N}) = f(\omega_N^x\omega_N^y)\)
5.卷积
6.Misc(多项式全家桶)
\(\aleph_0\). 例题讲解
P3803
题意简述:给定多项式 \(f(x),g(x)\),求 \(h(x) = f(x)g(x)\)。
讲解:就是个板子 发现 \(h(x)\) 的定义式 \(f(x)g(x)\) 恰好是点值乘法,于是 将 \(f,g\) FFT 然后乘起来 IFFT 回去就行了。
P1919
题意简述:给定大整数 \(x,y \le 10^{10^6}\),求 \(z = xy\)。
讲解:也是个板子 将大整数拆位当作多项式处理,此时得到的 \(Z(x) = X(x)Y(x)\) 会满足 \(Z(10) = xy\),但是我们不能直接算 \(Z(10)\),不然直接 \(\log^2 (x+y)\) 爆掉。于是考虑把进位一位一位传上去,这样复杂度可以接受。
P3338
题意简述:
给出 \(n\) 个实数 \(q_1,q_2, \dots q_n\),求对于每一个 \(j\),
\]
,考虑凑成乘法形式
FFT/NTT 学习笔记的更多相关文章
- FFT&NTT学习笔记
具体原理就不讲了qwq,毕竟证明我也不太懂 FFT(快速傅立叶变换)&NTT(快速数论变换) FFT //求多项式乘积 //要求多项式A和多项式B的积多项式C //具体操作就是 //DFT(A ...
- FFT和NTT学习笔记_基础
FFT和NTT学习笔记 算法导论 参考(贺) http://picks.logdown.com/posts/177631-fast-fourier-transform https://blog.csd ...
- FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅲ
第三波,走起~~ FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅰ FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅱ 单位根反演 今天打多校时 1002 被卡科技了 ...
- FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅰ
众所周知,tzc 在 2019 年(12 月 31 日)就第一次开始接触多项式相关算法,可到 2021 年(1 月 1 日)才开始写这篇 blog. 感觉自己开了个大坑( 多项式 多项式乘法 好吧这个 ...
- FFT、NTT学习笔记
参考资料 picks miskcoo menci 胡小兔 unname 自为风月马前卒 上面是FFT的,学完了就来看NTT吧 原根 例题:luogu3803 fft优化后模板 #include < ...
- FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅱ
因为垃圾电脑太卡了就重开了一个... 前传:多项式Ⅰ u1s1 我预感还会有Ⅲ 多项式基础操作: 例题: 26. CF438E The Child and Binary Tree 感觉这题作为第一题还 ...
- 快速傅里叶变换(FFT)学习笔记(未完待续)
目录 参考资料 FFT 吹水 例题 普通做法 更高大尚的做法 定义与一部分性质 系数表达式 点值表达式 点值相乘??? 卷积 复数 单位根 DFT IDFT 蝴蝶迭代优化 单位根求法 实现.细节与小优 ...
- NTT学习笔记
和\(FFT\)相对应的,把单位根换成了原根,把共轭复数换成了原根的逆元,最后输出的时候记得乘以原\(N\)的逆元即可. #include <bits/stdc++.h> using na ...
- NTT 学习笔记
引入 \(\tt NTT\) 和 \(\tt FFT\) 有什么不一样呢? 就是 \(\tt NTT\) 是可以用来取模的,而且没有复数带来的精度误差. 最最重要的是据说 \(\tt NTT\) 常数 ...
随机推荐
- 5G的发布加快了智慧城市/三维物联网等行业的发展
最近很多人发现自己的5G手机突然没了5G信号,难道是美国搞的鬼? 不不不,这其实是因为5G的NSA基站被撤站了,官方已经做了部署,要大力推进SA网络建设.所以之前支持NSA模式的5G手机,现在都成了4 ...
- BUUCTF-[BJDCTF2020]认真你就输了
[BJDCTF2020]认真你就输了 下载通过16进制查看发现是压缩包,直接就binwalk分离查看. 分离直接得到几个文件,不过好像压缩包里的和外面的文件是一样的,所以直接翻一下目录 直接就找到了 ...
- openGauss内核:SQL解析过程分析
摘要:在传统数据库中SQL引擎一般指对用户输入的SQL语句进行解析.优化的软件模块.SQL的解析过程主要分为:词法.语法和语义分析. 本文分享自华为云社区< openGauss内核分析(三):S ...
- 719. 找出第 K 小的数对距离
719. 找出第 K 小的数对距离 这道题其实有那么一点二分猜答案的意思,也有很多类似题目,只不过这道题确实表达的不是很清晰不容易想到,题没问题,我的问题.既然是猜答案,那么二分边界自然就是距离最大值 ...
- java版第一个代码——HelloWorld!
java版第一个代码--HelloWorld! 今天来接触一下java代码: 事前准备 jdk的配置(推荐jdk8或jdk11) notepad++或idea软件 开始编写 建立文件夹存放代码 建立j ...
- linux 配置集群需要修改的东西
1. 服务器主机名 vi /etc/hostname 按Esc,然后:wq! ,保存,然后重启电脑 reboot 2.修改IP和mac,也可以设置成自动的,但一般是固定的 cd /etc/syscon ...
- 升级了Springboot版本后项目启动不了了
问题背景 项目上使用的springboot版本是2.1.1.RELEASE,现在因为要接入elasticsearch7.x版本,参考官方文档要求,需要将springboot版本升级到2.5.14. 本 ...
- Java---注解与反射
前言 近期在学习SSM框架的过程中发现在SSM框架中大量用到了反射与注解的知识,要想学好SSM框架,必须将注解与反射熟记于心,尤其是对Java反射机制的理解. 对于我这种记性不好的人来说"基 ...
- linux 常用操作搜集
1.去除空行 方法一:利用grep grep -v '^\s*$' test.txt 注:-v表示将匹配的结果进行反转,正则表达式匹配空行.(空行可包括空格符制表符等空白字符) 方法二:利用sed s ...
- 【Java中的线程】java.lang.Thread 类分析
进程和线程 联想一下现实生活中的例子--烧开水,烧开水时是不是不需要在旁边守着,交给热水机完成,烧开水这段时间可以去干一点其他的事情,例如将衣服丢到洗衣机中洗衣服.这样开水烧完,衣服洗的也差不多了.这 ...