• FFT 快速傅里叶变换浅析


              终于补完坑了哈哈哈

             这个东西很神奇,看了半天网上的解释和课件,研究了很长时间,算是大概明白了它的原理。

             话不多说先上图。

             

             我们要求的h(x)=f(x)*g(x),f(x)=Σai*x^i,g(x)=Σbi*x^i.

             朴素求复杂度是$n^2$的,但一个$x$次多项式在平面上可以由$x+1$个点唯一插值表示,所以我们可以先用求出$x+1$个点$(xi,f(xi))$和$(xi,g(xi))$,再求出$(xi,f(xi)*g(xi))$,就可以反解出$h(x)$的表达式。

             那么我们需要在$nlogn$的时间内干完这两步,首先xi的取值需要特殊取,令$xi=ζ_{n}^i$(不懂复数的同学可以自行百度),令n(多项式次数,不够的话也要补)=$2^m$,那么

              $(ζ_n^k=ζ_{n/2}^{k/2})$

                 这显然是一个分治的形式,一个节点可以转移到下一层的两个节点,而每个节点又由上一层的两个节点转移,一共$logn$层,所以复杂度是$nlogn$的。

                 所以按这个式子分治下去,a0,a2,a4会不停排到前边去,最后的顺序变成图里的0,4,2,6,1,5,3,7,即把它们的二进制补零后翻转然后重新排序(证明很好证,可以自行脑补)。

            放代码。


    typedef complex<double> E;
    for
    (int i = 1; i < n; i <<= 1) { E wn(cos(pi / i), f*sin(pi / i)); for (int j = 0; j < n; j += (i << 1)) { E w(1, 0); for (int k = 0; k < i; k++, w *= wn) { E x = a[j + k],y=w*a[j+k+i]; a[j + k] = x + y; a[j + k + i] = x - y; } } }

              第一个循环枚举每回合并的区间长度,然后j每回跳2*i个单位,前i个由x+y转移,后i个由x-y转移,对应图上由左边和左下转移的点和由左边和左上转移的点,至于为什么这么转移。。。。。

              第i层第k(从0开始)个节点代表的意义是把ζ(2^i,k%(2^i))带进一个多项式里所得的值,多项式为a0+a1*x+a2*x^2......,其中a数组是排好序的,举个例子:第二列第一个点是

    a0+a4(原数组的第四个)*x,第三个点为a2+a6*x,第四个也为a2+a6*x(不过因为x不同所以值不同),第三列第五个为a1+a5*x+a3*x^2+a7*x^3。

           又因为ζ(n,k)=-ζ(n,k+n/2),参考分治形式转移就很好解释了。

             1号点的x=ζ(2,0),二号点为ζ(2,1),

           f1=a0+a4*ζ(2,0)=f(3)+f(4)*ζ(2,0),

           f2=a0+a4*ζ(2,1)=a0-a4*ζ(2,2)=a0-a4*ζ(2,0)=f(3)-f(4)*ζ(2,0)。

             这就可以解释代码中w值相同但一个正一个负了。

             (有什么不懂的地方可以留言,我会及时补充的>_<)。

             (感谢lty大佬的帮助 )。

             

  • 相关阅读:
    47 在 Java 程序中怎么保证多线程的运行安全?
    46 线程池中 submit() 和 execute() 方法有什么区别?
    前端能力和后端能力
    在HTML中限制input 输入框只能输入纯数字
    footer固定在页面底部的实现方法总结
    在网站建设的时候需要考虑哪些因素?
    CENTOS中cat命令中文乱码 VIM乱码设置
    腾讯实验室LAMP搭建DZ
    运算符总结
    Typora专业写手都在用
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6215980.html
Copyright © 2020-2023  润新知