看完学会速傅立叶变换FFT

fft 即快速傅立叶变换。在很多计算机领域都用用处,例如数字图像处理、计算机网络。但他在算法竞赛中主要是用于多项式和生成函数相关的题目。
多项式表达方式简介系数表达式,即。坐标形式。每一个坐标用表示。显然,为了能够表示一个确定的多项式,需要个不同的坐标来表示。比较对于系数表示,多项式加法的时间复杂度是,多项式乘法的时间复杂度是。对于点值表示,多项式加法的时间复杂度同样是,但是乘法的时间复杂度就是(因为多项式乘法以后最高项次数为,我们只需要个坐标表示)。思考这样一来,我们就有一个想法,多项式乘法,是不是可以利用坐标表示做多项式乘法特别快这点来优化算法。
于是需要解决的最大的问题就是,多项式两种表示方法之间的互相转换。
求值朴素做法的时间复杂度是,即随便选取一个值带入,暴力计算。
差值朴素的做法时间复杂度是,即根据坐标进行高斯消元。
在介绍 fft 之前,得先学习 dft (离散傅里叶变换)算法。
dft由于对一个多项式的点值表达式的取是任意的,所以好的取法可能会使一个算法产生本质性的蜕变。
我们选取次单位复根作为来取值。
单位复根,这个方程的复数根为次单位根。
单位的个单位根分别为。
个单位根在复平面的坐标表示为,我们将这个记为。在复平面上形象的表示的话,就是下图:
单位根在多项式的应用我们将个单位根带入多项式可以得到个因变量结果,记为。
我们将个单位根的倒数作为自变量带入由作为系数的多项式,可以得到。
而当的时候,它为,其余时候,它为(通过等比数列求和)。于是有。
于是可以发现,将个单位根的倒数带入变换后的多项式,可以得到原来的多项式。
这样一来,我们利用个单位根的性质,完成了多项式两种表示方式之间的转换。
dft算法有了的取值,我们就可以得到的取值了。

直接暴力计算,两个方向转换的时间复杂均为。
fft那么 fft 算法是如何优化计算这一过程的?利用分治。
我们把一个多项式的计算分为偶数项的计算和奇数项的计算:
也就是说, fft 的思想就是不断得把一个多项式拆分成奇数多项式和偶数多项式,然后合并两个多项式的信息。
也就是说,如果我们已经得到了和,我们只需要就可以得到了。
每次都能把多项式的长度减小一半,于是时间复杂度就是。
模版c++ 是自带了复数 stl 的,即:
#include但是常数大,跑得慢,不如自己重载的好。
下面的模版必须要保证是的整数次幂。typedef double ld;const ld pi = acos(-1);struct c { ld r, i; c(ld r = 0, ld i = 0): r(r), i(i) {}};c operator + (const c& a, const c& b) { return c(a.r + b.r, a.i + b.i);}c operator - (const c& a, const c& b) { return c(a.r - b.r, a.i - b.i);}c operator * (const c& a, const c& b) { return c(a.r * b.r - a.i * b.i, a.r * b.i + a.i * b.r);}void fft(c x[], int n, int p) { for (int i = 0, t = 0; i t) swap(x[i], x[t]); for (int j = n >> 1; (t ^= j) >= 1); } for (int h = 2; h <= n; h <<= 1) { c wn(cos(p * 2 * pi / h), sin(p * 2 * pi / h)); for (int i = 0; i > 1; j < i + k; ++j) { u = x[j + k] * w; x[j + k] = x[j] - u; x[j] = x[j] + u; w = w * wn; } } } if (p == -1) for (i, 0, n) x[i].r /= n;}void conv(c a[], c b[], int n) { fft(a, n, 1); fft(b, n, 1); for (i, 0, n) a[i] = a[i] * b[i]; fft(a, n, -1);}例题a * b iihttps://acm.ecnu.edu.cn/problem/3007/
大整数相乘。
把每一位都看成是多项式其中一项的系数,那么大数最后的结果也就是多项式乘法系数的结果。
要进位处理。
hnoi2017 礼物显然是要计算的最小值,其中$0≤x
展开这个式子,
除了,其他的和与相关的项都可以在的时间内算出了
那么配个方,就可以求出最小值了,而是固定的
现在的问题就是求,我们可以用fft来解决
如果我们把多项式倒置,我们就能发现式子的和的下标和可以相同,我们可以利用多项式乘法同时算出卷积。
设,那么,这样就可以用fft算出来了
总的时间复杂度
#include#define inf 0x3fffffffusing namespace std;typedef double ld;const ld pi=acos(-1);struct c{ ld r,i; c(ld r=0,ld i=0):r(r),i(i){}};c operator + (const c& a, const c& b){ return c(a.r+b.r,a.i+b.i);}c operator - (const c& a, const c& b){ return c(a.r-b.r,a.i-b.i);}c operator * (const c& a, const c& b){ return c(a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r);} void fft(c x[],int n,int p){ for (int i=0,t=0;i

焊接与钎焊的区别是什么
三星note8发布会最新消息:三星note8震撼登场!值得买吗?三星note8深度评测
航空工业太航压力传感器系列
Kinect无地自容!精确200倍的体感设备诞生
富士康智能制造加速营合作基地正式揭牌启用
看完学会速傅立叶变换FFT
光谱共焦如何测量玻璃基板厚度
电阻、电感以及电容元件的交流电路分析
QuantumScape的固态电池实现技术性突破
买二手笔记本需要注意的细节
“坦克杀手”机器人可能给地面战带来革命
线虫分离器的工作原理及其特点的介绍
三路输出LED驱动器提供一种节省空间且经济高效的解决方案
LDO电路设计及关键参数
分布电容对电路及设备的影响
北京市科协访问河套国际产业与标准组织聚集区进行调研
BLDC电机爆品不断,如何挖掘下一个天量商机?
安科瑞能耗管理系统在医院的应用
MOS管什么情况下会遭受静电破坏?
半导体光刻胶重要性凸出,国产替代加速推进