问题描述
  离散傅立叶变换在信号处理中扮演者重要的角色。利用傅立叶变换,可以实现信号在时域和频域之间的转换。
  对于一个给定的长度为n=2m (m为整数) 的复数序列X0, X1, …, Xn-1,离散傅立叶变换将得到另一个长度为n的复数序列Y0, Y1, …, Yn-1。其中
  Yi=X0+X1wi+ X2w2i+ X3w3i+…+ Xn-1w(n-1)i
  其中w=e2πI/n=cos(2π/n)+I sin(2π/n),称为旋转因子,其中I为虚数单位,I2= –1。
  给定输入序列X,请输出傅立叶变换后的输出序列。

  由于所有的复数C都可以表示成C=a+Ib的形式,即由实部和虚部的和表示,所以C可以用一个二元组(a, b)来表示,用这种方法w可表示为(cos(2π/n), sin(2π/n))。复数的计算规则如下:
  (a1, b1)+(a2, b2)=(a1+a2, b1+b2)
  (a1, b1)(a2, b2)=(a1, b1)*(a2, b2)=(a1*a2-b1*b2, a1*b2+a2*b1)

  对于本题,你可以按照上面的公式直接计算,也可以按下面的方法计算。使用上面的公式的复杂度为O(n2),可以得到一半的分数,而下面的方法的复杂度为O(n log n),可以得到全部的分数。如果要使用上面的公式直接计算,请跳过下面的算法描述部分。

算法描述
  注意到上式中w=e2πI/n=cos(2π/n)+I sin(2π/n),所以wn+k=wk,这个公式将在下面的计算用用到。
  对上面的公式进行变形,得到:
  Yi
  =X0 + X1wi + X2w2i + X3w3i +…+ Xn-1w(n-1)i
  =X0 + X2w2i + X4w4i +…+ Xn-2w(n-2)i + wi(X1 + X3w2i + X5w4i +…+ Xn-1w(n-2)i)
  =(X0 + X2φi + X4φ2i +…+ Xn-2φ(n/2-1)i) + wi(X1 + X3φi + X5φ2i +…+ Xn-1φ(n/2-1)i)
  其中φ=w2。利用这个公式可得
  Yi+n/2=(X0 + X2φi+n/2 + X4φ2(i+n/2) +…+ Xn-2φ(n/2-1) (i+n/2)) + wi(X1 + X3φ(i+n/2) + X5φ2(i+n/2) +…+ Xn-1φ(n/2-1) (i+n/2))
  其中φi+n/2=w2i+n=w2ii
  所以当i<n/2时,令pi=X0 + X2φi + X4φ2i +…+ Xn-2φ(n/2-1)i,qi= X1 + X3φi + X5φ2i +…+ Xn-1φ(n/2-1)i,则Yi=pi+wiqi,Yi+n/2= pi+wi+n/2qi
  利用上面的公式,我们可以得到一种快速计算旋转因子为w的傅立叶变换的方法如下(快速傅立叶变换):
  算法Y=Fourier(X, n, w)
  参数:X={Xi}为待变换的序列,n为序列的长度(2的整数次幂),w为旋转因子
  结果:X的傅立叶变换Y={Yi}
  1. 计算{X0, X2, X4, …, Xn-2}在旋转因子为φ=w2时的傅立叶变换序列{pi}
  2. 计算{ X1, X3, X5, …, Xn-1}在旋转因子为φ=w2时的傅立叶变换序列{qi}
  3. 对于0<=i<n,计算Yi=pi+wiqi。其中w0=(1, 0),wi=wi-1*w,你要设置一个临时变量进行累乘而不能每次重新计算wi
  使用这种方法,即可在O(n log n)的时间内计算傅立叶变换。
输入格式
  输入的第一行包含一个整数n,表示待变换的序列的长度,n是2的整数次幂。n<=16384。
  接下来n行,每行2个实数a, b表示序列中的一个元素为(a, b)。
输出格式
  输出n行,每行两个实数,表示经过变换后的序列。为了防止运算时的误差影响结果的输出,请将结果中的每一个实数除以n后保留两位小数。
样例输入
4
1.0 0.0
1.0 0.0
0.0 0.0
0.0 0.0
样例输出
0.50 0.00
0.25 0.25
0.00 0.00
0.25 -0.25
【分析】
也是裸题。
 /*
宋代苏轼
《临江仙·夜饮东坡醒复醉》
夜饮东坡醒复醉,归来仿佛三更。家童鼻息已雷鸣。敲门都不应,倚杖听江声。
长恨此身非我有,何时忘却营营。夜阑风静縠纹平。小舟从此逝,江海寄余生。
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <iostream>
#include <string>
#include <ctime>
#define LOCAL
const double Pi = acos(-1.0);
const int MAXN = + ;
using namespace std;
typedef long long ll;
struct Num {
double a , b;
//构造函数
Num(double x = ,double y = ) {a = x; b = y;}
//复数的三种运算
Num operator + (const Num &c) {return Num(a + c.a, b + c.b);}
Num operator - (const Num &c) {return Num(a - c.a, b - c.b);}
Num operator * (const Num &c) {return Num(a * c.a - b * c.b, a * c.b + b * c.a);}
}x1[MAXN] , x2[MAXN]; //注意loglen为log后的长度
void change(Num *t, int len, int loglen){
//蝶形变换后的序列编号
for (int i = ; i < len; i++){
int x = i, k = ;
for (int j = ; j < loglen; j++, x >>= ) k = (k << ) | (x & );
if (k < i) swap(t[k], t[i]);
}
}
//基2-FFT
void FFT(Num *x, int len, int loglen){
change(x, len, loglen);
int t = ;
//t为长度
for (int i = ; i < loglen; i++, (t <<= )){
int l = , r = l + t;
while (l < len){
//初始化
Num a, b, wo(cos(Pi / t), sin(Pi / t)), wn(, );
for (int j = l; j < l + t; j++){
a = x[j];
b = x[j + t] * wn;
//蝶形计算
x[j] = a + b;
x[j + t] = a - b;
wn = wn * wo;
}
//注意是合并所以要走2t步
l = r + t;
r = l + t;
}
}
}
//离散傅里叶变换
void DFT(Num *x, int len, int loglen){
int t = (<<loglen);
for (int i = ; i < loglen; i++){
t >>= ;
int l = , r = l + t;
while (l < len){
Num a, b, wn(, ), wo(cos(Pi / t), -sin(Pi / t));
for (int j = l; j < l + t; j++){
a = x[j] + x[j + t];
b = (x[j] - x[j + t]) * wn;
x[j] = a;
x[j + t] = b;
wn = wn * wo;
}
l = r + t;
r = l + t;
}
}
change(x, len, loglen);
for (int i= ; i < len; i++) x[i].a /= len;
}
int solve(char *a, char *b){
int len1, len2, len, loglen;
int t, over;
len1 = strlen(a) << ;
len2 = strlen(b) << ;
len = ;
loglen = ;
while (len < len1) len <<= , loglen++;
while (len < len2) len <<= , loglen++;
//处理len1
for (int i = ; i < len; i++){
if (a[i]) x1[i].a = a[i] - '', x1[i].b = ;
else x1[i].a = x1[i].b = ;
}
for (int i = ; i < len; i++){
if (b[i]) x2[i].a = b[i] - '', x2[i].b = ;
else x2[i].a = x2[i].b = ;
}
FFT(x1, len, loglen);
FFT(x2, len, loglen);
for (int i = ; i < len; i++) x1[i] = x1[i] * x2[i]; DFT(x1, len, loglen);
over = len = ;
//转换成十进制的整数
for (int i = ((len1 + len2) / ) - ; i >= ; i--){
t = (int)((double)x1[i].a + (double)over + 0.5);
a[len++] = t % ;
over = t / ;
}
while (over){
a[len++] = over % ;
over /= ;
}
return len;
}
//输出
void print(char *str, int len){
for(len--; len>= && !str[len];len--);
if(len < ) putchar('');
else for(;len>=;len--) putchar(str[len]+'');
printf("\n");
}
char a[MAXN] , b[MAXN]; int main() {
int n; scanf("%d", &n);
for (int i = ; i < n; i++) scanf("%lf%lf", &x1[i].a, &x1[i].b);
int t = ;
while ((<<t) < n) t++;
FFT(x1, n, t);
for (int i = ; i < n; i++) printf("%.2lf %.2lf\n", x1[i].a / n, x1[i].b / n);
return ;
}

【清橙A1084】【FFT】快速傅里叶变换的更多相关文章

  1. FFT 快速傅里叶变换 学习笔记

    FFT 快速傅里叶变换 前言 lmc,ikka,attack等众多大佬都没教会的我终于要自己填坑了. 又是机房里最后一个学fft的人 早背过圆周率50位填坑了 用处 多项式乘法 卷积 \(g(x)=a ...

  2. CQOI2018 九连环 打表找规律 fft快速傅里叶变换

    题面: CQOI2018九连环 分析: 个人认为这道题没有什么价值,纯粹是为了考算法而考算法. 对于小数据我们可以直接爆搜打表,打表出来我们可以观察规律. f[1~10]: 1 2 5 10 21 4 ...

  3. 「学习笔记」FFT 快速傅里叶变换

    目录 「学习笔记」FFT 快速傅里叶变换 啥是 FFT 呀?它可以干什么? 必备芝士 点值表示 复数 傅立叶正变换 傅里叶逆变换 FFT 的代码实现 还会有的 NTT 和三模数 NTT... 「学习笔 ...

  4. FFT —— 快速傅里叶变换

    问题: 已知A[], B[], 求C[],使: 定义C是A,B的卷积,例如多项式乘法等. 朴素做法是按照定义枚举i和j,但这样时间复杂度是O(n2). 能不能使时间复杂度降下来呢? 点值表示法: 我们 ...

  5. [C++] 频谱图中 FFT快速傅里叶变换C++实现

    在项目中,需要画波形频谱图,因此进行查找,不是很懂相关知识,下列代码主要是针对这篇文章. http://blog.csdn.net/xcgspring/article/details/4749075 ...

  6. matlab中fft快速傅里叶变换

    视频来源:https://www.bilibili.com/video/av51932171?t=628. 博文来源:https://ww2.mathworks.cn/help/matlab/ref/ ...

  7. FFT快速傅里叶变换算法

    1.FFT算法概要: FFT(Fast Fourier Transformation)是离散傅氏变换(DFT)的快速算法.即为快速傅氏变换.它是根据离散傅氏变换的奇.偶.虚.实等特性,对离散傅立叶变换 ...

  8. FFT快速傅里叶变换

    FFT太玄幻了,不过我要先膜拜HQM,实在太强了 1.多项式 1)多项式的定义 在数学中,由若干个单项式相加组成的代数式叫做多项式.多项式中的每个单项式叫做多项式的项,这些单项式中的最高项次数,就是这 ...

  9. [学习笔记]FFT——快速傅里叶变换

    大力推荐博客: 傅里叶变换(FFT)学习笔记 一.多项式乘法: 我们要明白的是: FFT利用分治,处理多项式乘法,达到O(nlogn)的复杂度.(虽然常数大) FFT=DFT+IDFT DFT: 本质 ...

随机推荐

  1. ManagerDay-2

    新工作开始了两个星期 基本没有什么产出,主要还是适应新岗位和学东西.作为一个由高级开发转初级PM的人,要学要接触的还有太多. 公司给我安排了一个刚刚起步的项目,可能也是我从业三年接触到的最大的一个项目 ...

  2. Redis 和 Memcached 的区别详解

    Redis的作者Salvatore Sanfilippo曾经对这两种基于内存的数据存储系统进行过比较: Redis支持服务器端的数据操作:Redis相比Memcached来说,拥有更多的数据结构和并支 ...

  3. Yii框架tips

    db组件 'schemaCachingDuration'=>3600, 为什么不起做用?需要开缓存 如何在页面下边显示sql的查询时间在log组件的routes中加入 array('class' ...

  4. Gof-23种设计模式名称列表

    工欲善其事,必先利其器. 在真正使用设计模式之前,必须知道各个设计模式对应的场景.设计模式是针对某种固定的场景下产生的固定解决方案.只有明确的场景,才会有明确的设计方式和方法. 设计模式全集: Abs ...

  5. MySQL忘记密码 办法

    在my.ini配置文件中,[mysqld]下面加上一句话,skip-grant-tables:然后重启mysql ,在cmd 页面中,直接进入mysql数据库 mysql -uroot -p不需要输入 ...

  6. (8/18)重学Standford_iOS7开发_协议、block、动画_课程笔记

    第八课: 1.协议 另一种安全处理id类型的方式如:id <MyProtocol> obj a.声明 //协议一般放于.h文件中或者在类的.h文件中 @protocol Foo <X ...

  7. 利用UI_APPEARANCE统一设置UITabBarItem样式

    -(void)setupTabBarItemAttributes{ //attributes NSMutableDictionary *selectedAttrs= [NSMutableDiction ...

  8. bootstrap学习笔记--bootstrap网格系统

    移动设备优先 移动设备优先是 Bootstrap 3 的最显著的变化. 在之前的 Bootstrap 版本中(直到 2.x),您需要手动引用另一个 CSS,才能让整个项目友好的支持移动设备. 现在不一 ...

  9. gwt中java与js的相互调用

    1. java通过jsni调用内部js Button button = new Button("java调用内部jsni的js方法"); button.addClickHandle ...

  10. Spring 4.x org.springframework.http.converter.json.MappingJacksonHttpMessageConverter ClassNotFoundException:

    Spring 4.x The first major version of Jackson is no longer supported in Spring 4. The class you want ...