问题:

  已知A[], B[], 求C[],使:

    

  定义C是A,B的卷积,例如多项式乘法等。

  朴素做法是按照定义枚举i和j,但这样时间复杂度是O(n2).

  能不能使时间复杂度降下来呢?

点值表示法:

  我们把A,B,C看作表达式。

  即:

    A(x)=a+ a1* x + a2 * x2 +...

  将A={(x1,A(x1)), (x2,A(x2)), (x3,A(x3))...}叫做A的点值表示法。

  那么使用点值表示法做多项式乘法就很简单了:对应项相乘。

  那么,如何将A和B转换成点值表示法,再将C转化回系数表示法(即最初的表示方法)呢?

  如果任取n个点,按照定义计算,那么还是O(n2)的。

  这样就要用到快速傅里叶变换。

快速傅里叶变换:

  既然任取n个点,按照定义计算太慢,就要找一些特殊点。

  我们用n个n次单位复数根(1的n次方根,涉及到复数,1的方根不止1和-1)来计算:

    1的n次方根是,其中i是虚数单位。

  我们定义wn = e^(2∏i)是主n次单位根,那么所有n次单位复数根都是它的次方。

  我们要求出A(wnk),就要采用分治思想。

  我们将奇偶系数分离(先假设n为偶数),即定义

      A1(x)=a+ a2* x + a4 * x2 +...

      A2(x)=a+ a3* x + a5 * x2 +...

  那么A(x)=A1(x2) + xA2(x2)。

  要计算A(wnk)=A1((wnk)2) + wnkA2((wnk)2),

  就要用到(wnk)2 = wn/2k mod (n / 2)(证略)。

  所以A(wnk)=A1(wn/2k mod (n / 2)) + wnkA2(wn/2k mod (n / 2))

  我们发现A1,A2都是n/2项的,且只需要算wn/2k的值,那么这就和开始的问题一样了,可以分治。

  边界也很容易:n=1的时候A1本身就是值。

  合并解。

  A(wnk)=A1(wn/2k mod (n / 2)) + wnkA2(wn/2k mod (n / 2))

  那么可以A(wnk)和A(wnk+n/2)一起算(0<=k<n/2):

    设u = A1(wn/2k), t = wnkA2(wn/2k),

    那么A(wnk) = u + t

      A(wnk+n/2) = A1(wn/2k) + wnk + n/2 A2(wn/2k)

            = A1(wn/2k) + wnk  wnn/2 A2(wn/2k)

            = A1(wn/2k) - wnk A2(wn/2k)

            = u - t

  所以这样就能算出A的点值表示法。

  一个问题:分治要求n是2的幂,不是怎么办? 补0, 直到是2的幂。

  剩下的问题:如何把C转化回系数表示法。

快速傅里叶逆变换:

  我们把C做一遍快速傅立叶变换,只是求的是wnn, wnn-1, ..., wn1的值而不是wn0, wn1, ..., wnn-1的值,最后每一项除以n即可。

  证略。

 void Rader(complex y[],int len)
 {
     int i,j,k;
     , j = len/;i < len-;i++)
     {
         if(i < j)swap(y[i],y[j]);
         k = len/;
         while( j >= k)
         {
             j -= k;
             k /= ;
         }
         if(j < k)j += k;
     }
 }
 void FFT(complex y[],int len,int on)  //on = 1 快速傅里叶变换, on = -1 快速傅里叶逆变换
 {
     Rader(y,len);
     ;h <= len;h <<= )
     {
         complex wn(cos(-on**PI/h),sin(-on**PI/h));  //e^ki = cosk + isink
         ;j < len;j += h)
         {
             complex w(,);
             ;k++)
             {
                 complex u = y[k];
                 complex t = w*y[k+h/];
                 y[k] = u+t;
                 y[k+h/] = u-t;
                 w = w*wn;
             }
         }
     }
     )
         ;i < len;i++)
             y[i].r /= len;
 }
39 //复数实现略

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. [C++] 频谱图中 FFT快速傅里叶变换C++实现

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

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

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

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

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

  7. FFT快速傅里叶变换

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

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

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

  9. FFT(快速傅里叶变换)

    学习了FFT用来求多项式的乘法,看了算导上的介绍,上面讲的非常明白,概括一下FFT的原理就是,我们在计算多项式的乘法时,如果暴力模拟的话是n^2 复杂度的,就像小学学的竖式乘法一样,比如一个n位数乘上 ...

随机推荐

  1. HDOJ-ACM1017(JAVA)

    问题描述: 简单来说,就是 输入N,然后输入N个数据块,一个数据块包含(n,m),并计算0 < a < b < n 且 (a^2+b^2 +m)/(ab) 为整数.其中a,b只要符合 ...

  2. [转]2-SAT问题及其算法

    转自:http://www.cppblog.com/MatoNo1/archive/2011/07/13/150766.html [2-SAT问题]现有一个由N个布尔值组成的序列A,给出一些限制关系, ...

  3. Redis和Memcache的对比

    我这段时间在用redis,感觉挺方便的,但比较疑惑在选择内存数据库的时候到底什么时候选择redis,什么时候选择memcache,然后就查到下面对应的资料,是来自redis作者的说法(stackove ...

  4. A Tour of Go Pointers

    Go has pointers, but no pointer arithmetic. Struct fields can be accessed through a struct pointer. ...

  5. java_list<String> string[]拼接json

    private String getJsonStr(List<String> jsonKeyList, String[] values){ String jsonStr = "{ ...

  6. C# .Net基础知识点解答

    原文地址 1. 什么是.NET?什么是CLI?什么是CLR?IL是什么?JIT是什么,它是如何工作的?GC是什么,简述一下GC的工作方式? 通俗的讲,.Net是微软开发应用程序的一个平台: CLI是C ...

  7. 【课程分享】基于Lucene4.6+Solr4.6+Heritrix1.14+S2SH实战开发从无到有垂直搜索引擎

    对这个课程有兴趣的朋友,能够加我的QQ2059055336和我联系,能够和您分享.  课程介绍:最有前途的软件开发技术--搜索引擎技术  搜索引擎作为互联网发展中至关重要的一种应用,已经成为互联网各个 ...

  8. Java 加密解密 对称加密算法 非对称加密算法 MD5 BASE64 AES RSA

    版权声明:本文为博主原创文章,未经博主允许不得转载. [前言] 本文简单的介绍了加密技术相关概念,最后总结了java中现有的加密技术以及使用方法和例子 [最简单的加密] 1.简单的概念 明文:加密前的 ...

  9. hdu2571 命运 动态规划Dp

    转载请注明出处:http://blog.csdn.net/u012860063 题目链接:pid=2571" target="_blank">http://acm. ...

  10. 使用phpize建立php扩展(Cannot find config.m4)(转)

    php源码:/root/soft/php-5.3.4php安装: /usr/local/php [root@ns root]# phpizeCannot find config.m4.Make sur ...