zoukankan      html  css  js  c++  java
  • FFT

    FFT

    用来解决多项式相乘问题。

    算法流程:

    将两个多项式转为点值表达-->点值表达相乘搞出答案多项式的点值表达-->将答案的点值表达变为系数表达-->输出。

    其中将系数表达变为点值表达的算法叫做 dft

    对于一个(n)多项式(F(x)),我们需要求出(F'(x)=F(omega_n^x))。(点值表达)

    这个过程我们可以分治求解,理论依据是以下两个公式:

    [color{blue}{F(omega_n^k)=Fl(omega_{n/2}^k)+omega_n^kFr(omega_{n/2}^k)\ F(omega_n^{k+n/2})=Fl(omega_{n/2}^k)-omega_n^kFr(omega_{n/2}^k)} ]

    证明(1):

    [F(omega_n^k)=Fl((omega_{n/2}^k)^2)+omega_{n/2}^k imes Fr((omega_{n/2}^k)^2) \ =Fl(omega_n^{2k})+omega_{n/2}^k imes Fr(omega_n^{2k})\=Fl(omega_{n/2}^k)+omega_n^kFr(omega_{n/2}^k) ]

    证明(2):

    [ F(omega_n^{k+n/2})=Fl((omega_n^{k+n/2})^2)+omega_n^{k+n/2} imes Fr((omega_n^{k+n/2})^2)\ ]

    (omega_n^{k+n/2}=omega_n^k imesomega_n^{n/2}=-omega_n^k)

    [ =Fl(omega_{n}^{2k+n})-omega_n^k imes Fr(omega_{n}^{2k+n}) ]

    (omega_n^{kmod n}=w_n^k)

    [= Fl(omega_{n/2}^k)-omega_n^kFr(omega_{n/2}^k) ]

    所以要求出一个多项式的点值表达,我们可以分治(Theta (n log n))解决。

    设点值为(G),系数为(F)

    根据点值代入的原理,我们可以知道:

    [G_k=sum_{i=1}^n(omega_n^k)^i imes F_i ]

    通过这个式子,我们可以将(G)反推回(F)

    先说结论:

    [color{blue}n imes F[k] = sum_{i=1}^{n}(omega_n^{-k})^i imes G_i ]

    证明:代入得:

    [sum_{i=1}^{n}(omega_n^{-k})^i imes G_i=sum_{j=1}^n(omega_n^{-k})^jsum_{i=1}^n(omega_n^j imes F_i) ]


    FFT 实际上是优化卷积的一种方法,

    卷积 :

    [C_k=sum_{i=1}^nA_i imes B_{k-i} ]

    容易发现两个多项式相乘实际上就是卷积的一种形式。

    题目: ZJOI2014力

    给出 (n) 个数,(q_i),给出(F_j)的定义如下:

    [ F_j=sum_{i<j}dfrac{qi imes qj}{(i-j)^2}-sum _{i>j} dfrac{qi imes qj}{(i-j)^2} ]

    (E_i=dfrac{F_i}{q_i}),求(E_i)

    显然

    [ E_j=sum_{i=1}^{j-1}dfrac{qi}{(i-j)^2}-sum_{i=j+1}^{n} dfrac{q_i}{(i-j)^2} ]


    (这时我参考了一下题解)

    (g_i=dfrac{1}{i^2}),原式化为,我们再定义(dfrac{1}{0}=0)

    [ E_j=sum_{i=1}^{j} qi imes g_{j-i} - sum _{i=j}^{n} q_i imes g_{j-i} ]

    我们惊喜的发现左边已经变成了卷积的形式!

    有一个想法就是我们可以分别计算两边的卷积,最后再加上。

    右边的式子我们可以套路解决:

    [ sum_{i=j}^n q_i imes g_{(i-j)} \ 在g那里加上j,再将 sum 转化为关于g的表述:\ sum_{i=1}^{n-j}=q_{i+j} imes g_i ]

    继续使用套路,设(q'_i=q_{n-i})

    [ sum_{i=1}^{n-j}q_{i+j} imes g_i \ =sum_{i=1}^{n-j}q'_{n-(n-(i+j))} imes g_i ]

    还有一个套路: 设(t=n-j):

    [ sum_{i=1}^{t}q'_{(n-(i+j))} imes g_i \ = sum_{i=1}^{t}q'_{(n-i-j)} imes g_i \ = sum_{i=1}^{t}q'_{(t-i)} imes g_i \ ]

    又是一个卷积!这样我们就可以进行fft了!

    总结一下:

    • 我们需要两个数组: (q'_i=q_{n-i})(g_x=dfrac{1}{x^2})
    • 然后我们要进行两次fft,然后再相减:

    [ Left_j=sum_{i=1}^{j} qi imes g_{j-i} \ Right_t=sum_{i=1}^{t}q'_{(t-i)} imes g_i ]

  • 相关阅读:
    linux 命令
    linux 后门防范
    linux date
    shell 常用参数
    linux rule策略
    vlan对服务器要注意的事情
    STL vector——c++
    蛇形矩阵
    简单a+b
    小 X 与数字(ten)
  • 原文地址:https://www.cnblogs.com/guodongLovesOi/p/12268763.html
Copyright © 2011-2022 走看看