zoukankan      html  css  js  c++  java
  • FFT,NTT入门

    -1.前置知识

    复数

      复数单位(i):定义为(i^2=-1)(i)可以直接参与运算。
      复数:形如(z=a+bi)的数被称为复数,其中(a)称为实部,(b)称为虚部。可以发现,当(b=0)的时候,(z)就是实数。
      复平面:建立直角坐标系。对于复数(z=a+bi),其在复数平面上的坐标就是((a,b));即横轴表示实部,纵轴表示虚部。另外,一个复数同样可以被表示为复平面上的一个从原点出发的向量
      复数的运算:设(x=a+bi,y=c+di),定义如下:
        (x+y=a+bi+c+di=(a+c)+(b+d)i)
        (x-y=(a+bi)-(c+di)=(a-c)+(b-d)i)
        (xy=(a+bi)(c+di)=ac+(bc+ad)i+bdi^2=(ac-bd)+(bc+ad)i)
      复数的三角函数形式:前面说到,复数在复平面上即是一个向量。因此我们可以定义复数(z=a+bi)的模长为(|z|=sqrt{a^2+b^2}),即向量对应的模长;定义复数(z=a+bi)的幅角为向量到实轴正方向的角度为辐角。
    复数向量
      反过来,我们可以通过模长(|z|)与幅角( heta)唯一确定一个复数,即(z=|z|(cos heta+isin heta))
      因此,对于复数(x=|x|(cos heta_x+isin heta_x),y=|y|(cos heta_y+isin heta_y)),复数的乘法也等价于:
      (xy=|x||y|((cos heta_xcos heta_y-sin heta_xsin heta_y)+i(sin heta_xcos heta_y+sin heta_ycos heta_x))=|x||y|(cos( heta_x+ heta_y)+isin( heta_x+ heta_y)))
      即模长相乘,辐角相加

    单位根

      单位根被定义为:方程(x^n=1)在复数域内的所有解。
      莽了?不用担心,我们先聊一聊单位圆
    单位圆
      可以发现,单位圆实际上就是所有的起点在原点且模长为(1)的向量的终点集合
      另一方面,根据复数运算性质,我们发现,所有解的模长一定是(1)
      再想一想,解的辐角应该是:(frac{2pi imes 0}{n},frac{2pi imes 1}{n},...,frac{2pi imes (n-1)}n),只有这些向量自乘(n)次之后,才会落到实轴正半轴上来。
      因此,我们得到了结果:(n)次单位根(n),记为(omega_n^{0sim(n-1)}),其中(omega_n^k)为一个模长为(1),辐角为(frac{2pi imes k}{n})的复数。
      下图展示了(n=3)时的单位根(们):
    w3
      接下来,有一些关于单位根的重要性质,大家可以按照切蛋糕来理解。
        1.(omega_n^k=(omega_n^1)^k),证明略;
        2.(omega_n^j imesomega_n^k=omega_n^{j+k}),可用上式证明;
        3.(omega_{2n}^{2k}=omega_n^k)。比如,你一次在蛋糕上切(frac18),那么你切(4)块就可以得到半块蛋糕;一次切(frac14),那么你就需要(2)块。
        4.折半引理:当(n)为偶数的时候,(omega_{n}^{(k+frac n2)}=-omega_n^k)。其中(omega_n^{(k+frac n2)}=omega_n^k imesomega_n^{frac n2}),也就是将(omega_n^k)再转半圈之后得到的向量。此时它们模长相等,方向相反,它们就是相反数。

    单位根反演

      定理:

    [frac1nsum_{k=0}^{n-1}omega_n^{ak}=[n|a] ]

      证明:
      当(n|a)的时候:
        设(a=nt),原式中所有(omega_n^{ak}=omega_n^{ntk}=omega_n^0=1),因此原式(=frac1nsum_{k=0}^{n-1}1=1)
      当(n ot|a)的时候:
        等比数列求和:

    [egin{aligned} frac1nsum_{k=0}^{n-1}omega_n^{ak}&=frac1nsum_{k=0}^{n-1}(omega_n^a)^k\ &=frac1n imes frac{1-omega_n^{an}}{1-omega_n^a}\ &=frac1n imes frac{1-1}{1-omega_n^1}\ &=0 end{aligned}]

      于是就证完了。

    0.卷积

      卷积是定义在函数上的运算。
      对于函数(f(n))(g(n)),其卷积((f*g)(n))就是:

    [(f*g)(n)=int_{-infty}^{infty}f( au)g(n- au) ext d au ]

      我知道你觉得它很没用,所以这里还有离散的表达:

    [(f*g)(n)=sum_{ au=-infty}^{infty}f( au)g(n- au) ]

      你说计算机处理不了实数?好吧,这里还有最后一个,定义在有限序列(f)(g)上的卷积:

    [(f*g)(n)=sum_{i=0}^nf(i)g(n-i) ]

      是不是很熟悉?这就是我们常见的多项式乘法!
      因此,算法竞赛中常常用卷积优化算法 FFT 来进行多项式乘法运算。

    1.FFT

      

  • 相关阅读:
    dotNet开发游戏微端
    另类Unity热更新大法:代码注入式补丁热更新
    KSFramework配置表:扩展表格解析类型
    KSFramework常见问题:Excel如何进行SVN协作、差异比较?
    KSFramework常见问题:Lua脚本热重载,内存状态数据丢失?
    KEngine:Unity3D资源的打包、加载、调试监控
    KEngine策划指南:配置表格的编辑与编译
    开发遇到的奇葩问题
    初始加载时edittext不自动获取焦点的方法
    android 监控软键盘确定 搜索 按钮并赋予点击事件
  • 原文地址:https://www.cnblogs.com/crashed/p/13048082.html
Copyright © 2011-2022 走看看