zoukankan      html  css  js  c++  java
  • fft&ntt

    FFT

    单位根:

    在复平面上,以原点为圆心,$1$为半径作圆,所得的圆叫单位圆。以圆点为起点,圆的$n$等分点为终点,做$n$个向量,设幅角为正且最小的向量对应的复数为

    $omega_n$,称为$n$次单位根。

    单位根计算公式:$omega_{n}^{k}=cos frac{k imes 2 pi}{n} + i sinfrac{k imes 2 pi}{n}$

    单位根性质:

    1.$omega_{n}^{x+y}=omega_{n}^{x} imes omega{n}^{y}$

    证明方法:由复数的乘法运算方法为幅角相加,模长及单位根的定义可得

    2.$omega_{n}^{k}=omega_{2n}^{2k}$

    直接由公式证明即可:$cos frac{k imes 2 pi}{n} + i sinfrac{k imes 2 pi}{n}=cos frac{2k imes 2 pi}{2n} + i sinfrac{2k imes 2 pi}{n}$

    3.$omega_{n}^{k}=- omega_{n}^{k+ frac{n}{2}}$

    证明方法:$omega_{n}^{frac{n}{2}}=cos frac{frac{n}{2} imes 2 pi}{n} + i sinfrac{frac{n}{2} imes 2 pi}{n}=cos pi + sin pi =-1$

    4.$omega_{n}^{k}=omega_{n}^{k+n}$

    证明方法:公式

    5.$omega_{n}^{0}=omega_{n}^{n}=1$

     

    快速傅里叶变换

    设 $A(x)=a_0+a_1*x+a_2*{x^2}+a_3*{x^3}+a_4*{x^4}+a_5*{x^5}+ dots+a_{n-2}*x^{n-2}+a_{n-1}*x^{n-1}$

    按指数的奇偶分类:

    令$A1(x)=a_0+a_2*{x^2}+a_4*{x^4}+ dots+a_{n-2}*x^{n-2}$

    $A2(x)=a_1*x+a_3*{x^3}+a_5*{x^5}+ dots+a_{n-1}*x^{n-1}=x(a_1+a_3*{x^2}+a_5*{x^4}+ dots+a_{n-1}*x^{n-2})$

    所以$A(omega_{n}^{k})=A1(omega_{n}^{2k})+omega_{n}^{k}*A2(omega_{n}^{2k})$

    由$omega_{n}^{k}=- omega_{n}^{k+ frac{n}{2}}$可知
    $A1( omega_{n}^{k+ frac{n}{2}})=A1(omega_{n}^{k}),A2(omega_{n}^{k+ frac{n}{2}})=-A2(omega_{n}^{k})$

    $ herefore A(omega_{n}^{k+ frac{n}{2}})=A1(omega_{n}^{2k})-omega_{n}^{k}*A2(omega_{n}^{2k})$

    由此可见,我们只需要计算$omega_{n}{k} (k in [0,frac{n}{2}-1])$ 就可以了

    容易发现这样计算序列${a_0,a_1,dots ,a_{n-1}}$只需要下传$log n$ 层

    时间复杂度O(n log n)

     

    快速傅里叶逆变换

    Our's aim is to change 点值表示法 into 系数表示法

    既然系数表示法能转成点值表示法,那么我们不妨将点值表示法的序列${y_0,y_1,y_2,dots,y_{n-1}}$当成系数表示法

    然后设序列c为以序列y为系数表示法得到的点值表示法,看看序列c和实际的系数表示法直接的联系

    $c_k= sum y_i * (omega_n^{-k})^i $

    $=sum_{i=0}^{n-1} sum_{j=0}^{n-1} a_j*(omega_n^i)^j * (omega_n^i)^k$

    $=sum_{j=0}^{n-1} a_j* sum_{i=0}^{n-1} (omega_n^{i})^{j-k}$

    由性质3可知,当$j-k != 0$ 时,$sum_{i=0}^{n-1} (omega_n^{i})^{j-k}=0$

    所以$c_k=a_k * n$

    理论部分就到此结束了qwq

     

    代码实现

    像这样正着传会进行很多的重复操作

    所以我们要倒着传才能达到$O(n log n)$

    倒着传的流程图如下

    打表发现,最后一层的数值为a[下标二进制反转]

    fft完结撒花

    NTT: 

    快速数论变换,可以取模(但只能处理系数为整数的多项式运算)

    原根:

    Definition:对于$g,p in Z$,如果$g^i space mod space p,(i in [1,p-1])$的值互不相同,那么称g为p的原根

    Instance: $998244353,1004535809,469762049的原根都是3$

    性质

    我们将$g^{(p-1)/n}当做原根中的omega_{n}^{1}$

    性质1:指数乘法运算法则

    性质2:指数乘法运算法则

    性质3:由于$(g^{k*(p-1)/n})^2=(g^{k*(p-1)/n+(p-1)/2})^2,根据原根的性质可知g^{k*(p-1)/n}!=g^{k*(p-1)/n+(p-1)/2}$,所以这两个东西是相反数

    性质4:费马小定理

    性质5:费马小定理

    过程&代码实现同fft

    ntt完结撒花

  • 相关阅读:
    C#屏幕截图
    WPF转换器用法示例
    WPF自定义数字输入框控件
    LINQ 用法,返回结果不是在定义时取值,而是在调用时实时取值,有意思!
    类泛型--必须继承接口
    wpf在异步中给前台赋值
    VS Code中Matlab插件安装设置
    Python 自动给数字前面补0
    Tensorflow (1)
    解决Keras在IDE集成环境中找不到nvcc
  • 原文地址:https://www.cnblogs.com/handsome-zlk/p/14158113.html
Copyright © 2011-2022 走看看