参考:http://blog.csdn.net/f_zyj/article/details/76037583
如果公式炸了请去我的csdn博客:http://blog.csdn.net/luyouqi233/article/details/79323568
原文即是一篇很好的FFT入门博客,但是笔者打算为了日后的学习,则将原篇章的结构删改增添一下,如有思路上的雷同十分正常。
“是时候打开FFT的大门了!”

预备知识:

1.至少知道基础数论与一定解三角形知识(大概是高中水平)。
2.定义\(i=\sqrt{-1}\)
3.引入复数(即形如\(a+bi\)(a,b均为实数)的数的集合)
4.\((cos\theta+i\times sin\theta)^k=cos(k\theta)+i\times sin(k\theta)\)
5.显然我们对多项式FFT之后得到的答案不是我们想要的,那么这时候就需要反着用FFT把式子再变回去(本文记做IFFT)。

这里证明一下第四条,用归纳法。
显然当\(k=1\)时成立。
当\(k\)成立时,我们有:
\((cos\theta+i\times sin\theta)^{k+1}\)
\(=(cos\theta+i\times sin\theta)^k\times (cos\theta+i\times sin\theta)\)
\(=(cos(k\theta)+i\times sin(k\theta))\times (cos\theta+i\times sin\theta)\)
\(=cos(k\theta)cos\theta+i\times sin(k\theta)cos\theta+i\times cos(k\theta)sin\theta+i^2\times sin(k\theta) sin\theta\)
\(=cos(k\theta)cos\theta-sin(k\theta) sin\theta+i\times (sin(k\theta)cos\theta+cos(k\theta)sin\theta)\)
\(=cos((k+1)\theta)+i\times sin((k+1)\theta)\)
得证。

问题引入:

设\(A(x)=\sum_{i=0}^{n-1}a_ix^i,B(x)=\sum_{i=0}^{n-1}b_ix^i\),求\(A(x)\times B(x)\)后的多项式系数。

初探:

显然我们有一个\(O(n^2)\)的解法,但是实在是太慢了。
考虑到一个\(n-1\)次多项式可以看做是定义在复数域上的函数,则我们一定可以找到n个点来唯一确定这个函数。
当然我们也可以通过这些点来表示这个多项式。
假设:
\(A(x)\)被表示为:\(<(x_0,y_{a_0}),(x_1,y_{a_1}),\ldots,(x_{2n-2},y_{a_{2n-2}})>\)
\(B(x)\)被表示为:\(<(x_0,y_{b_0}),(x_1,y_{b_1}),\ldots,(x_{2n-2},y_{b_{2n-2}})>\)
显然\(A(x)\times B(x)\)被表示为:\(<(x_0,y_{a_0}y_{b_0}),(x_1,y_{a_1}y_{b_1}),\ldots,(x_{2n-2},y_{a_{2n-2}}y_{b_{2n-2}})>\)

这里多取了点的原因在于\(A(x)\times B(x)\)是一个\(2n-2\)次多项式,则至少要取\(2n-1\)个点才能保证正确。

但是显然还是\(O(n^2)\)的。

再试:

考虑设\(A(x_i)=A_0(x_i^2)+x_iA_1(x_i^2)\),其中:
\(A_0(x)=a_0+a_2x+a_4x^2+\ldots+a_{n-2}x^{\frac{n}{2}+1}\)
\(A_1(x)=a_1+a_3x+a_5x^2+\ldots+a_{n-1}x^{\frac{n}{2}+1}\)

其实就是按照系数下标的奇偶性分类了一下。

此时我们再令取点的\(x\)值为\(<x_0,x_1,\ldots,x_{\frac{n}{2}-1},-x_0,-x_1,\ldots,-x_{\frac{n}{2}-1}>\)
我们发现把\(x\)平方后我们的取值瞬间缩小了一半,而原式唯一变化的就是\(A_1(x)\)前的符号。
看起来我们似乎找到了\(O(nlogn)\)的可行方案。
但是很可惜,这样优秀的\(x\)取值的性质只会保留一次,也就是说我们只是得到了一个\(O(\frac{n^2}{2})\)。
如何才能每次将问题的规模缩小一半是我们的目标。

插曲:

有个人告诉你:不如试试\(X_n=cos\frac{2\pi}{n}+i\times sin\frac{2\pi}{n}\) 的 \(0\ldots n-1\)次方作为\(x\)的取值。

这块大家一直有个疑惑:这是怎么构造出来的啊?
事实上傅里叶变换最早是应用于信号处理上的,傅里叶提出:任何连续周期信号可以由一组适当的正弦曲线组合而成。
多项式可以看做非连续周期信号,然后通过各种奇妙的姿势让它逼近正弦曲线的组合形,详情可以看松松松WC2018的课件。
“逼近”显然用到了微积分,不适合初学者,所以就直接跳过了。(其实我也不会……)
(再多说一点吧,其实上面和下面的数学推理完全可以从物理层面理解,还是可以参考松松松WC2018的课件)

继续:

那么令取点的\(x\)值为\(<X_n^0,X_n^1,\ldots,X_n^{n-1}>\)
我们可知:
\((X_n^{k})^2\)

\(=X_n^{2k}\)

\(=cos\frac{2k\times 2\pi}{n}+i\times sin\frac{2k\times 2\pi}{n}\)

\(=cos\frac{2k\pi}{\frac{n}{2}}+i\times sin\frac{2k\pi}{\frac{n}{2}}\)

\(=X_{\frac{n}{2}}^k\)


\(X_n^{k}\)

\(=cos\frac{k\times 2\pi}{n}+i\times sin\frac{k\times 2\pi}{n}\)

根据三角函数的周期性可知,\(k\)对\(n\)取模显然不会对答案造成影响。
于是我们有\(X_n^{k}=X_n^{k\%n}\)

那么显然对于\(<(X_n^0)^2,(X_n^1)^2,\ldots,(X_n^{n-1})^2>\)

它等效于\(<X_{\frac{n}{2}}^0,X_{\frac{n}{2}}^1,\ldots,X_{\frac{n}{2}}^{\frac{n}{2}-1},X_{\frac{n}{2}}^0,X_{\frac{n}{2}}^1,\ldots,X_{\frac{n}{2}}^{\frac{n}{2}-1}>\)

我们好像看到了\(O(nlogn)\)的曙光了。

尾声:

显然我们可以对\(x\)的取值折半,然后对于左右区间的\(x\)值递归下去即可。
Q1:诶等等,“再试”里面的内容好像没有应用上啊……

A1:那就转化一下,其实我们只需要求一个区间的\(A_0(x)\)和\(A_1(x)\)值递归下去求\(A(x)\)即可。
也就是说其实我们是得到了:
\(<(A_0)_0,(A_0)_1,\ldots,(A_0)_{\frac{n}{2}-1},(A_1)_0,(A_1)_1,\ldots,(A_1)_{\frac{n}{2}-1}>\)

Q2:这好像是画蛇添足……

A2:emmm……我说这个可以用于常数优化你信吗……
显然\(A(X_n^k)=(A_0)_{k\%\frac{n}{2}}+X_n^k(A_1)_{k\%\frac{n}{2}}\)

取模是因为,不要忘了我们的取值是由两个一样的左右区间合并在一起的。

那么我们得到了\(<A_0,A_1,\ldots,A_{n-1}>\)

(其中\(A_k=A(X_n^k)\))

我们好像把这个序列的长度减少了一半诶!那自然是快了二倍啊。

不要忘了n要满足始终是2的倍数,所以n要取2的整数次幂,同时将没用的次幂的系数填成0。

Q3:IFFT怎么做啊?

A3:继续看下去……?

补遗:

略讲一下IFFT。
显然我们可以把FFT的最初算法(也就是DFT)看做两个矩阵相乘。

两个矩阵分别一个填\((X_n^k)^m\),一个填系数,可以上参考处原博客看矩阵。

那么我们把第一个矩阵变成逆矩阵岂不是为IFFT?
其实就是这样,并且事实上就是填\(((X_n^{-k})^m)/n\),具体证明过程看参考处原博客。
剩下的做法就和FFT一样啦。

谢幕:

事实上我上述讲的内容其实没有多少用(滑稽。
因为你理解半天也不如不理解知道怎么用然后默写下来。
但是理解了更好背啊。

例题:

模板:
HDU1402:A * B Problem Plus:http://www.cnblogs.com/luyouqi233/p/8448969.html

应用:
BZOJ3527:[ZJOI2014]力:http://www.cnblogs.com/luyouqi233/p/8452117.html

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

模板:快速傅里叶变换(FFT)的更多相关文章

  1. [模板] 快速傅里叶变换/FFT/NTT

    简介 FFT是多项式乘法的一种快速算法, 时间复杂度 \(O(n \log n)\). FFT可以用于求解形如\(C_i = \sum_{j=0}^i A_jB_{i-j}\)的式子. 如果下标有偏差 ...

  2. [模板]快速傅里叶变换(FFT)

    Miskcoo大佬的多项式全家桶传送门 rvalue大佬的FFT讲解传送门 用途 将多项式快速(nlogn)变成点值表达,或将点值表达快速变回系数表达(逆变换),(多数时候)来达到求卷积的目的 做法 ...

  3. 快速傅里叶变换(FFT)_转载

    FFTFFT·Fast  Fourier  TransformationFast  Fourier  Transformation快速傅立叶变换 P3803 [模板]多项式乘法(FFT) 参考上文 首 ...

  4. Algorithm: 多项式乘法 Polynomial Multiplication: 快速傅里叶变换 FFT / 快速数论变换 NTT

    Intro: 本篇博客将会从朴素乘法讲起,经过分治乘法,到达FFT和NTT 旨在能够让读者(也让自己)充分理解其思想 模板题入口:洛谷 P3803 [模板]多项式乘法(FFT) 朴素乘法 约定:两个多 ...

  5. 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)

    再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...

  6. 快速傅里叶变换FFT

    多项式乘法 #include <cstdio> #include <cmath> #include <algorithm> #include <cstdlib ...

  7. [学习笔记] 多项式与快速傅里叶变换(FFT)基础

    引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积, 而代码量却非常小. 博主一年半前曾经因COGS的一 ...

  8. 快速傅里叶变换FFT& 数论变换NTT

    相关知识 时间域上的函数f(t)经过傅里叶变换(Fourier Transform)变成频率域上的F(w),也就是用一些不同频率正弦曲线的加 权叠加得到时间域上的信号. \[ F(\omega)=\m ...

  9. 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】

    原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...

  10. 快速傅里叶变换(FFT)

    扯 去北京学习的时候才系统的学习了一下卷积,当时整理了这个笔记的大部分.后来就一直放着忘了写完.直到今天都腊月二十八了,才想起来还有个FFT的笔记没整完呢.整理完这个我就假装今年的任务全都over了吧 ...

随机推荐

  1. myeclipse激活后server不能用问题

    一般是由于激活失败造成的,这种问题就卸了重新安装吧,目前还没有找到合理的方法解决,这个还真的看哥们的运气了,我是装了不下5遍才激活成功的,一般情况下,在激活的时候 出现下图的情况,Usercode写好 ...

  2. SpringCloud 学习(二) :服务注册与发现Eureka

    Spring Cloud应用中可以支持多种的服务治理框架,比如Eureka.Consul.Zookeeper等,现在我们用的是consul,本文以SpringCloud Dalston.SR5版本介绍 ...

  3. oracle数据库之rownum和rowid用法

    Rownum 和 Rowid是Oracle数据库所特有的,通过他们可以查询到指定行数范围内的数据记录.   以下通过例子讲解: -- 为了方便,首先,查找dept表中的所有. select deptn ...

  4. Log4j简单配置解析

    log4j.rootLogger=ERROR, stdoutlog4j.logger.tk.mybatis.simple.mapper=TRACElog4j.appender.stdout=org.a ...

  5. 【深度学习的实用层面】(一)训练,验证,测试集(Train/Dev/Test sets)

    在配置训练.验证.和测试数据集的过程中做出正确的决策会更好地创建高效的神经网络,所以需要对这三个名词有一个清晰的认识. 训练集:用来训练模型 验证集:用于调整模型的超参数,验证不同算法,检验哪种算法更 ...

  6. chown命令详情

    基础命令学习目录首页 原文链接:https://www.jb51.net/article/98255.htm chown将指定文件的拥有者改为指定的用户或组,用户可以是用户名或者用户ID:组可以是组名 ...

  7. Python基础_eval(),exec(),globals(),locals(),compile()

    转发:http://www.cnblogs.com/yyds/p/6276746.html 1. eval函数 函数的作用: 计算指定表达式的值.也就是说它要执行的Python代码只能是单个运算表达式 ...

  8. js格式化json字符串和json对象

    1,格式化json对象 var json = {"@odata.context":"$metadata#AddTableOne_466281s","v ...

  9. Scrum Meeting 6 -2014.11.12

    今天apec最后一天,大部分任务都差不多了,局部测试问题不大.大家修复下小细节就可以开始整合了. Member Today’s task Next task 林豪森 协助测试及服务器部署 协助测试及服 ...

  10. Task 6.2冲刺会议十 /2015-5-23

    今天是第一个冲刺阶段的最后一天,主要把做出来的程序进行了初步的测试,在一台笔记本上运行程序,摄像头可以工作也能听到声音和麦克多的运转也还可以,两台计算机同时在一个局域网中通信的时候也可以实现.不过后续 ...