FFT快速傅里叶变换

摘自:https://www.cnblogs.com/RabbitHu/p/FFT.html

快速傅里叶变换(FFT)是一种能在O(nlogn)O(nlog?n)的时间内将一个多项式转换成它的点值表示的算法。

点值表示:设A(x)是一个n−1次多项式,那么把n个不同的x代入,会得到n个y。这n对(x,y)唯一确定了该多项。由多项式可以求出其点值表示,而由点值表示也可以求出多项式。

设有两个n−1次多项式A(x)和B(x)),我们的目标是——把它们乘起来。普通的多项式乘法是O(n^2),但有趣的是,两个用点值表示的多项式相乘,复杂度是O(n)的!具体方法:C(xi)=A(xi)×B(xi)。

高精度乘法:等价于x=10的A(x)*B(x)

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <complex>
 6 #define space putchar(‘ ‘)
 7 #define enter putchar(‘\n‘)
 8 using namespace std;
 9 typedef long long ll;
10 template <class T>
11 void read(T &x){
12     char c;
13     bool op = 0;
14     while(c = getchar(), c < ‘0‘ || c > ‘9‘)
15     if(c == ‘-‘) op = 1;
16         x = c - ‘0‘;
17     while(c = getchar(), c >= ‘0‘ && c <= ‘9‘)
18         x = x * 10 + c - ‘0‘;
19     if(op) x = -x;
20 }
21 template <class T>
22 void write(T x){
23     if(x < 0) putchar(‘-‘), x = -x;
24     if(x >= 10) write(x / 10);
25     putchar(‘0‘ + x % 10);
26 }
27 const int N = 1000005;
28 const double PI = acos(-1);
29 typedef complex <double> cp;
30 char sa[N], sb[N];
31 int n = 1, lena, lenb, res[N];
32 cp a[N], b[N], omg[N], inv[N];
33 void init(){
34     for(int i = 0; i < n; i++){
35         omg[i] = cp(cos(2 * PI * i / n), sin(2 * PI * i / n));
36         inv[i] = conj(omg[i]);
37     }
38 }
39 void fft(cp *a, cp *omg){
40     int lim = 0;
41     while((1 << lim) < n) lim++;
42     for(int i = 0; i < n; i++){
43         int t = 0;
44         for(int j = 0; j < lim; j++)
45             if((i >> j) & 1) t |= (1 << (lim - j - 1));
46         if(i < t) swap(a[i], a[t]); // i < t 的限制使得每对点只被交换一次(否则交换两次相当于没交换)
47     }
48     for(int l = 2; l <= n; l *= 2){
49         int m = l / 2;
50     for(cp *p = a; p != a + n; p += l)
51         for(int i = 0; i < m; i++){
52             cp t = omg[n / l * i] * p[i + m];
53             p[i + m] = p[i] - t;
54             p[i] += t;
55         }
56     }
57 }
58 int main(){
59     scanf("%s%s", sa, sb);
60     lena = strlen(sa), lenb = strlen(sb);
61     while(n < lena + lenb) n *= 2;
62     for(int i = 0; i < lena; i++)
63         a[i].real(sa[lena - 1 - i] - ‘0‘);
64     for(int i = 0; i < lenb; i++)
65         b[i].real(sb[lenb - 1 - i] - ‘0‘);
66     init();
67     fft(a, omg);
68     fft(b, omg);
69     for(int i = 0; i < n; i++)
70         a[i] *= b[i];
71     fft(a, inv);
72     for(int i = 0; i < n; i++){
73         res[i] += floor(a[i].real() / n + 0.5);
74         res[i + 1] += res[i] / 10;
75         res[i] %= 10;
76     }
77     for(int i = res[lena + lenb - 1] ? lena + lenb - 1: lena + lenb - 2; i >= 0; i--)
78         putchar(‘0‘ + res[i]);
79     enter;
80     return 0;
81 }
82
83 //可以预处理ωkn和ω−kn,分别存在omg和inv数组中。调用fft时,如果无需取倒数,则传入omg;如果需要取倒数,则传入inv。

原文地址:https://www.cnblogs.com/lbz007oi/p/12288348.html

时间: 2024-10-13 23:00:06

FFT快速傅里叶变换的相关文章

准零基础搞懂FFT快速傅里叶变换及其实现程序(二)

上一篇文章我们了解了DFT的原理,FFT是基于DFT的更适合计算机运算的算法,本文我们就正式开始学习FFT的原理. 首先我么先来宏观的看一下FFT.如果我们把整个FFT的算法看成一个黑盒子的话,那么它的输入就是时间波形信号,比如声音波形(横轴为时间,纵轴为振幅).外什么FFT要比DFT速度更快呢?下面(图1)解释了FFT和DFT的(对于计算机的)算法复杂度 图1 从上面的数学表达式可以看出,一个1024采样点的FFT比DFT块了102.4倍.如果傅里叶变换的数量级更大,FFT的速度优势会更明显.

FFT —— 快速傅里叶变换

问题: 已知A[], B[], 求C[],使: 定义C是A,B的卷积,例如多项式乘法等. 朴素做法是按照定义枚举i和j,但这样时间复杂度是O(n2). 能不能使时间复杂度降下来呢? 点值表示法: 我们把A,B,C看作表达式. 即: A(x)=a0 + a1* x + a2 * x2 +... 将A={(x1,A(x1)), (x2,A(x2)), (x3,A(x3))...}叫做A的点值表示法. 那么使用点值表示法做多项式乘法就很简单了:对应项相乘. 那么,如何将A和B转换成点值表示法,再将C转

【Delphi】如何在三轴加速器的频谱分析中使用FFT(快速傅里叶变换)算法

关于傅里叶变换的作用,网上说的太过学术化,且都在说原理,已经如何编码实现,可能很多人有个模糊影响,在人工智能,图像识别,运动分析,机器学习等中,频谱分析成为了必备的手段,可将离散信号量转换为数字信息进行归类分析. 今天这里将的不是如何实现,而是如何使用傅里叶变换 但频谱分析中,涉及到的信号处理知识对大部分软件开发的人来说,太过于晦涩难懂,傅里叶变换,拉普拉斯,卷积,模相,实数,虚数,复数,三角函数等等,已经能让软件工程师望而却步,造成懂知识的人无法开发,懂开发的人无法分析,而同时具备两种技能的人

【bzoj2179】FFT快速傅里叶变换(优化高精度乘法)

#include<bits/stdc++.h> using namespace std; #define pi acos(-1) typedef complex<double> C; const int N=201100; int n,m,l,r[N],ans[N]; C a[N],b[N]; char s[N],t[N]; void fft(C *a,int f){ for(int i=0;i<n;++i) if(r[i]>i) swap(a[i],a[r[i]]);

【模板】FFT快速傅里叶变换

1 struct Complex{ 2 double x, y; 3 inline Complex(double xx=0, double yy=0){ 4 x=xx; y=yy; 5 } 6 inline Complex operator + (Complex a){ 7 return Complex(x+a.x, y+a.y); 8 } 9 inline Complex operator - (Complex a){ 10 return Complex(x-a.x, y-a.y); 11 }

浅谈FFT(快速傅里叶变换)

本文主要简单写写自己学习FFT的经历以及一些自己的理解和想法. FFT的介绍以及入门就不赘述了,网上有许多相关的资料,入门的话推荐这篇博客:FFT(最详细最通俗的入门手册),里面介绍得很详细. 为什么要学习FFT呢?因为FFT能将多项式乘法的时间复杂度由朴素的$O(n^2)$降到$O(nlogn)$,这相当于能将任意形如$f[k]=\sum\limits _{i+j=k}f[i]*f[j]$的转移方程的计算在$O(nlogn)$的时间内完成.因此对于想要进阶dp的同学来说,FFT是必须掌握的技能

FFT 快速傅里叶变换

这个东西很神奇,看了半天网上的解释和课件,研究了很长时间,算是大概明白了它的原理. 话不多说先上图. 我们要求的h(x)=f(x)*g(x),f(x)=Σai*x^i,g(x)=Σbi*x^i. 朴素求复杂度是n2的,但一个x次多项式在平面上可以由x+1个点唯一插值表示,所以我们可以先用求出x+1个点(xi,f(xi))和(xi,g(xi)),再求出(xi,f(xi)*g(xi)),就可以反解出    h(x)的表达式. 那么我们需要在nlogn的时间内干完这两步,首先xi的取值需要特殊取,令x

快速傅里叶变换FFT

快速傅里叶变换FFT DFT是信号分析与处理中的一种重要变换.但直接计算DFT的计算量与变换区间长度N的平方成正比,当N较大时,计算量太大,直接用DFT算法进行谱分析和信号的实时处理是不切实际的. 1.直接计算DFT 长度为N的有限长序列x(n)的DFT为: 2.减少运算量的思路和方法 思路:N点DFT的复乘次数等于N2.把N点DFT分解为几个较短的DFT,可使乘法次数大大减少.另外,旋转因子WmN具有周期性和对称性. (考虑x(n)为复数序列的一般情况,对某一个k值,直接按上式计算X(k)值需

快速傅里叶变换(FFT)算法【详解】

快速傅里叶变换(Fast Fourier Transform)是信号处理与数据分析领域里最重要的算法之一.我打开一本老旧的算法书,欣赏了JW Cooley 和 John Tukey 在1965年的文章中,以看似简单的计算技巧来讲解这个东西. 本文的目标是,深入Cooley-Tukey  FFT 算法,解释作为其根源的“对称性”,并以一些直观的python代码将其理论转变为实际.我希望这次研究能对这个算法的背景原理有更全面的认识. FFT(快速傅里叶变换)本身就是离散傅里叶变换(Discrete