FFT从入门到使用(ACM/OI)

本文深入浅出地介绍了快速傅里叶变换(FFT)和数论优化的快速傅里叶变换(NTT)的概念。从DFT、IDFT、FFT的官方定义出发,探讨了FFT的效率提升和实际应用。详细讲解了复数、单位复根等基础知识,以及FFT的分治思想和具体步骤。同时,文章还介绍了NTT在计算模数情况下的多项式乘法中的作用,以及原根和生成子群等相关数论概念。通过实例和代码,帮助读者理解和掌握FFT与NTT的运用。
摘要由CSDN通过智能技术生成

(首先膜一发高中生qwq亏我学了信号处理原理专业课了竟然是看高中生的博客才能看懂qwq。。。大概断断续续看了几十篇吧。。。

序言

可能是许久以来写的最认真的一篇了吧,加上今天感觉不太舒服,但是觉得要开始扎实的学点什么,所以,就从现在开始吧。感谢所有认真写博客的人的帮助!!!希望我也能贡献点什么qwq。。。

一直想学FFT,之前牛客的多小有一道组合数学就用FFT写的,而且当时还傻乎乎的用唯一分解定理,但是自己好久没静下心学什么了,而且自己的数学功底又不好,导致一直学不会。看了很多人的博客也没看明白,尤其是原根。但是看了一个OIer的博客,顿时明白了。。。然后赶紧记录下来。

另外,本文的代码实现全部参考匡斌(kuangbin)的模板(2018.7更新)

前言

你搜索这个关键词就已经知道这一是个数学的东西了。只想学会用很简单,但是这远远不够。所以在看这个博客之前应该先学一下复数的基本知识。

好了下面进入正文。

1.DFT IDFT FFT官方定义?

离散傅里叶变换(Discrete Fourier Transform,缩写为DFT),是傅里叶变换时域频域上都呈离散的形式,将信号的时域采样变换为其DTFT的频域采样。

FFT是一种DFT的高效算法,称为快速傅立叶变换(fast Fourier transform)。

                                              ——百度百科

在百度百科上能找到DFT和FFT这两个定义。正如定义,FFT和DFT实际上按照结果来看的话是一样的,但是FFT比较快的计算DFT和IDFT(离散反傅里叶变换·)。

快速数论变换(NTT)是快速傅里叶变换(FFT)在数论基础上的实现。

是不是有点迷QAQ?既然是官方定义那肯定不能让你看懂才对嘛~下面我们一一解释~

2.为什么要使用FFT?

我们在这里引入一个例子:求多项式乘积的朴素算法。

大家平时求    f(x) = a^{_{1}}f(x) = a_{1}x^2 + b_{1}x + c_{1}   与  g(x) = a_{2}x^2 + b_{2}x + c_{2}  的乘积时候,是怎么进行的呢?

我们令

K(x) = f(x)*g(x) = a_{1}x^2 *a_{2}x^2 + a_{1}x^2*b_{2}x + a_{1}x^2*c_{2} + b_{1}x *b_{2}x^2 + b_{1}x*b_{2}x + b_{1}x*c_{2} + c_{1} *a_{2}x^2 + c_{1}*b_{2}x + c_{1}*c_{2}

那么很显然我们进行了9次运算,复杂度是O(n^2).(具体代码实现不再展开)

但是如果数字足够大呢?比如100000?那朴素算法可太慢啦(;′⌒`),

3.学习FFT

3.1 在学习FFT之前...

3.1.1什么是FFT

FFT,即为快速傅氏变换,是离散傅氏变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。——360百科

如果上一个例子用朴素算法太慢啦!所以我们要用FFT进行优化,复杂度会降为O(nlog(n))

3.1.2项式的系数表示法与点值表示法

一个多项式,我们可以怎样来表示呢?

系数表示法就是用一个多项式的各个项系数来表达这个多项式。比如:

f(x) = a_{1}x^2 + b_{1}x + c_{1}\Leftrightarrow f(x) = \{a_{1},b_{1},c_{1}\}

点值表示法是把这个多项式看成一个函数,从上面选取n+1个点,从而利用这n+1个点来唯一的表示这个函数。为什么用(n+1)个点就能唯一的表示这个函数了呢?想一下高斯消元法,两点确定一条直线。再来一个点,能确定这个直线中的另一个参数,那么也就是说(n+1)个点能确定n个参数(不考虑倍数点之类的没用点)。如下:

\\f_{1}(x) = y_{1} = a_{0} + a_{1}x _{1}+ a_{2}x_{1}^2 + a_{3}x_{1}^3+...+a_{n}x_{1}^n\\ f_{2}(x) = y_{2} = a_{0} + a_{1}x_{2} + a_{2}x_{2}^2 + a_{3}x_{2}^3+...+a_{n}x_{2}^n\\ f_{3}(x) = y_{3} = a_{0} + a_{1}x_{3} + a_{2}x^2_{3} + a_{3}x_{3}^3+...+a_{n}x_{3}^n\\ f_{4}(x) = y_{4} = a_{0} + a_{1}x_{4} + a_{2}x_{4}^2 + a_{3}x_{4}^3+...+a_{n}x_{4}^n\\..\\ f_{n}(x) = y_{n} = a_{0} + a_{1}x_{n} + a_{2}x_{n}^2 + a_{3}x_{n}^3+...+a_{n}x_{n}^n\\

多项式由系数表示法转为点值表示法的过程,就成为DFT;

相对地,把一个多项式的点值表示法转化为系数表示法的过程,就是IDFT。

而FFT就是通过取某些特殊的x的点值来加速DFT和FFT的过程。

3.1.3复数的引入

复数分为实数和虚数。实数就是我们日常最常用的有理数和无理数。大家记得我们在开始学平方的时候,老师会说所有数的平方大于等于0对不对,那么虚数就引入了。虚数一般用i表示,对于虚数i,有i = \sqrt{-1}。另外,i对于虚数的意义,与1对于实数的意义是一样的。如果我说得不够明确,你可以看下面我引用的百科说明。

在数学中,虚数就是形如a+b*i的数,其中a,b是实数,且b≠0,i² = - 1。虚数这个名词是17世纪著名数学家笛卡尔创立,因为当时的观念认为这是真实不存在的数字。后来发现虚数a+b*i的实部a可对应平面上的横轴,虚部b与对应平面上的纵轴,这样虚数a+b*i可与平面内的点(a,b)对应。

可以将虚数bi添加到实数a以形成形式a + bi的复数,其中实数a和b分别被称为复数的实部和

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值