关于FFT原理部分的介绍,在网上已经有很多了,所以在此只讲代码实现部分的内容。

原理可以参考https://www.cnblogs.com/RabbitHu/p/FFT.html

推荐看完它的原理解释再来看这里的代码解释

废话不多说,上代码(多项式乘法)

#include <iostream>
#include <cstdio>
#include <cmath>
#define N 4000001
using namespace std;
struct cp//手写复数类可以卡常
{
double real,imag;
};
cp operator +(cp a,cp b)
{
return (cp){a.real+b.real,a.imag+b.imag};
}
cp operator -(cp a,cp b)
{
return (cp){a.real-b.real,a.imag-b.imag};
}

复数乘法:设$R_{a}$表示$a$的实部系数,$I_{a}$表示$a$的虚部系数

则$a*b$

$=(R_{a}+I_{a})*(R_{b}+I_{b})$

$=R_{a}*R_{b}+R_{a}*I_{b}+R_{b}*I_{a}+I_{a}*I_{b}$

因为$i^2=-1$

所以结果的实部为$R_{a}*R_{b}-I_{a}*I_{b}$

虚部为$R_{a}*I_{b}+R_{b}*I_{a}$

cp operator *(cp a,cp b)
{
  return (cp){a.real*b.real-a.imag*b.imag,a.real*b.imag+a.imag*b.real};
}
double pi=acos(-1.0);
int lim,rev[N],len;
cp w[N],inv[N],a[N],b[N];
void get_w()
{
for(int i=0;i<=lim;i++)
{
double angle=(double)i*2*pi/lim;
w[i].imag=sin(angle);
w[i].real=cos(angle);
inv[i]=(cp){w[i].real,-w[i].imag};
}
}

fft参数解释

$arr:$系数数组,在$fft$后变为点值数组,$arr_{i}$表示将$w^i_n$带入多项式后求得的值

$w:$预处理好的w单位根,在$fft$的时候正常带入即可,在$idft$的时候带入单位根的倒数(具体参见$idft$)void fft(cp *arr,cp *w)

{
for(int i=0;i<lim;i++)
{
//处理每一个系数在分治过程中的实际位置;
//if是因为只需交换一次,所以选择由小的一方来执行
if(i<rev[i]) swap(arr[i],arr[rev[i]]);
}
for(int i=2;i<=lim;i*=2)//枚举区间长度
{
int l=i/2;
for(int j=0;j<lim;j+=i)//枚举区间位置,这些区间是互不相交的
{
//枚举带入的单位根w(k,l),k>=l的单位根也可以在这里一并求出
for(int k=0;k<l;k++)
{

  

意义变更

在这里$arr$的意义从系数变为$w^k_i$的点值,$a_{j,j+i-1}$分别表示将$w^{0,i-1}_i$的点值

下面的的t相当于文首博客中的$w^k_n * A_2(w^k_{n \over 2})$

				cp t=arr[j+k+l]*w[lim/i*k];//w(k,i)=w(k/i,1)=w(n*k/i,n)
arr[j+k+l]=arr[j+k]-t;
arr[j+k]=arr[j+k]+t;
}
}
}
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<=n;i++) scanf("%lf",&a[i].real);
for(int i=0;i<=m;i++) scanf("%lf",&b[i].real);
lim=1;
while(lim<=n+m) len++,lim<<=1;//这样会比用cmath的log要快?
for(int i=0;i<lim;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1));
get_w();
fft(a,w);
fft(b,w);
for(int i=0;i<=lim;i++) a[i]=a[i]*b[i];
fft(a,inv);
for(int i=0;i<=n+m;i++) printf("%d ", (int)(a[i].real/lim+0.5));
  //除以lim的原因具体参见idft,0.5是为了四舍五入
}

FFT代码详解的更多相关文章

  1. BM算法  Boyer-Moore高质量实现代码详解与算法详解

    Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...

  2. ASP.NET MVC 5 学习教程:生成的代码详解

    原文 ASP.NET MVC 5 学习教程:生成的代码详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 ...

  3. Github-karpathy/char-rnn代码详解

    Github-karpathy/char-rnn代码详解 zoerywzhou@gmail.com http://www.cnblogs.com/swje/ 作者:Zhouwan  2016-1-10 ...

  4. 代码详解:TensorFlow Core带你探索深度神经网络“黑匣子”

    来源商业新知网,原标题:代码详解:TensorFlow Core带你探索深度神经网络“黑匣子” 想学TensorFlow?先从低阶API开始吧~某种程度而言,它能够帮助我们更好地理解Tensorflo ...

  5. JAVA类与类之间的全部关系简述+代码详解

    本文转自: https://blog.csdn.net/wq6ylg08/article/details/81092056类和类之间关系包括了 is a,has a, use a三种关系(1)is a ...

  6. Java中String的intern方法,javap&cfr.jar反编译,javap反编译后二进制指令代码详解,Java8常量池的位置

    一个例子 public class TestString{ public static void main(String[] args){ String a = "a"; Stri ...

  7. Kaggle网站流量预测任务第一名解决方案:从模型到代码详解时序预测

    Kaggle网站流量预测任务第一名解决方案:从模型到代码详解时序预测 2017年12月13日 17:39:11 机器之心V 阅读数:5931   近日,Artur Suilin 等人发布了 Kaggl ...

  8. 基础 | batchnorm原理及代码详解

    https://blog.csdn.net/qq_25737169/article/details/79048516 https://www.cnblogs.com/bonelee/p/8528722 ...

  9. 非极大值抑制(NMS,Non-Maximum Suppression)的原理与代码详解

    1.NMS的原理 NMS(Non-Maximum Suppression)算法本质是搜索局部极大值,抑制非极大值元素.NMS就是需要根据score矩阵和region的坐标信息,从中找到置信度比较高的b ...

随机推荐

  1. SQL系列(六)—— 过滤(where)

    在日常的应用中的,大多数业务场景都只是需要特定的数据,所以能够过滤筛选数据显得尤为至关重要.从需求角度分析,需要特定的数据,即需要一定条件的数据,即从全量数据中根据特定条件过滤出需要的数据. 如果需要 ...

  2. JAVAWEB之增删改查

    青年志愿者服务网(20分)   1.项目需求: 为了适应社会主义市场经济发展的需要,推动青年志愿服务体系和多层次社会保障体系的建立和完善,促进青年健康成长,石家庄铁道大学急需建设青年志愿者服务网,推进 ...

  3. .net Dapper 实践系列(6) ---事务删除(Layui+Ajax+Dapper+MySQL)

    目录 写在前面 实现步骤 写在最后 写在前面 上一小节,总结了事务多表更新的两种方法.一个是只更新原来的数据,一个是先删除原来的数据再往里面添加新的数据.而这一小节,说的是事务的多表删除. 实现步骤 ...

  4. vs2012新建单元测试

    多写单元测试也是算向优秀程序员迈进吧((ˇˍˇ)),就像我们小时候做算算术一样,老师会交给我们怎么样检验答案是否正确性.那么我们做程序员也一样,检验自己写的代码是否和我们预期的结果一样!项目小还行,但 ...

  5. C# 使用SuperSocket

    一.需求场景 (1)使用SuperSocket进行网络通信 二.所需软件 (1)SocketTool 三.实现步骤   (1)使用Nuget管理器安装SuperSocket.Engine 该插件已经包 ...

  6. tf.random_shuffle()函数解析

    tf.random_shuffle(value, seed=None, name=None) 函数就是随机地将张量沿第一维度打乱 value:将被打乱的张量. seed:一个 Python 整数.用于 ...

  7. 详细的Hadoop的入门教程-伪分布模式Pseudo-Distributed Operation

    一. 伪分布模式Pseudo-Distributed Operation 这里关于VM虚拟机的安装就不再介绍了,详细请看<VMware虚拟机的三种网络管理模式>一章介绍.这章只介绍hado ...

  8. 使用MHA实现MySQL主从复制高可用

    一.MHA简介        MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司的youshimaton(现就职于Fac ...

  9. 89.canvas制作爱心

    <!DOCTYPE html> <html> <head>     <title>JavaScript和html53D玫瑰花(程序员的情人节礼物)< ...

  10. Oracle使用expdp/impdp迁移数据

    Oracle使用expdp/impdp迁移数据 1.#以下步骤在开发库执行(expdp导出) 一.创建逻辑目录,该命令不会在操作系统创建真正的目录,最好以system等管理员创建. sqlplus / ...