zoukankan      html  css  js  c++  java
  • FFT

    1 问题描述
    多项式的系数表示法:设关于x的n-1次多项式,次数为i的系数为ai。

    [Aleft( x ight) = sumlimits_{j = 0}^{n - 1} {{a_j}{x^j}} ]

    多项式的点值表示法:用n个点可以确定一条曲线,

    [left( {{x_0},{y_0}} ight)left( {{x_1},{y_1}} ight) ldots left( {{x_{n - 1}},{y_{n - 1}}} ight)]

    其中x值各不相同。

    其中,系数表示法,对于两个多项式(设最高次数都是n-1)的加法来说,复杂度是O(n)的,而对于两个多项式的乘法来说,复杂度是O(n^2)的。而点值表示法对于多项式加法和乘法的复杂度都是O(n)。


    对于给出的两个多项式是系数表示法,而要求它们的乘积。可以使用FFT首先把系数表示法转化成点值表示法(这个复杂度可以nlog(n)实现),然后用点值表示法计算乘法(复杂度O(n)),然后把最后的点值表示法转化成系数表示法(这个复杂度可以nlog(n)实现),那么最后,两个系数表示的多项式乘法的复杂度就会变成nlog(n)。

    2 预备知识

    方程${omega ^n} = 1$在复数范围内有n个解(它们叫做n次单位复根)

    [{e^{frac{{2pi ik}}{n}}},k = 0,1, ldots ,n - 1]

    由复数的幂的定义${e^{iu}} = cos left( u ight) + isin left( u ight)$

    可得:

    [{left( {{e^{frac{{2pi ik}}{n}}}} ight)^n} = {e^{2pi ik}} = cos left( {2pi k} ight) + isin left( {2pi k} ight) = 1]

    设主n次单位根为${w_n} = {e^{frac{{2pi i}}{n}}}$

    所有的n次单位复根都是主n次单位根的幂。n个n次单位复根在乘法运算下形成一个群,

    [w_n^n = w_n^0 = 1]

    [w_n^iw_n^j = w_n^{i + j}]



    关于n次单位复根的一些性质。

    (1)对任何整数$ngeq 0,kgeq 0,d>0$,$w_{dn}^{dk}=w_{n}^{k}$

    证明:?[w_{dn}^{dk} = {left( {{e^{frac{{2pi i}}{{dn}}}}} ight)^{dk}} = {left( {{e^{frac{{2pi i}}{n}}}} ight)^k} = w_n^k]

    (2)对任意偶数n>0,

    [w_n^{frac{n}{2}} = {w_2} = ?- 1]

    证明:[w_n^{frac{n}{2}} = w_{2 cdot frac{n}{2}}^{1 cdot frac{n}{2}} = w_2^1 = {w_2} = ?- 1]

    (3)对于任意整数n>=1和不能被n整除的非零整数k,有

    [sumlimits_{j = 0}^{n - 1} {{{left( {w_n^k} ight)}^j}} ?= 0]

    证明:

    $sum_{j=0}^{n-1}(w_{n}^{k})^{j}=frac{(w_{n}^{k})^{n}-1}{w_{n}^{k}-1}=frac{(w_{n}^{n})^{k}-1}{w_{n}^{k}-1}=0$

    3 算法流程

    我们设给出的多项式为

    [Aleft( x ight) = sumlimits_{j = 0}^{n - 1} {{a_j}{x^j}} ]

    其中n是2的幂(如果不是,那么我们可以在后面补一些x的高次方,使得它们的系数为0),我们用向量表示这个系数

    [ar a = left( {{a_0},{a_1}, ldots ,{a_{n - 1}}} ight)]

    我们的目的是将它表示成一个点值,

    [left( {{x_0},{y_0}} ight)left( {{x_1},{y_1}} ight) ldots left( {{x_{n - 1}},{y_{n - 1}}} ight)]

    在这里,我们设

    [{x_i} = w_n^i]

    我们后面可以发现这样假设,可以使得计算的复杂度变为nlog(n)。如果确定了x,那么最后就是要求出这样一个向量:

    [ar y = left( {{y_0},{y_1}, ldots ,{y_{n - 1}}} ight)]

    其中

    [{y_i} = Aleft( {{x_i}} ight) = sumlimits_{j = 0}^{n - 1} {{a_j}w_n^{ij}} ]

    那么现在我们的问题变成给出向量$ar{a}$,求向量$ar{y}$

    我们发现,这个直接计算的复杂度是O(n^2)的。FFT(快速傅里叶变换)运用了分治的方法,我们把这个$ar{a}$按照奇数偶数分成两个新的向量

    [{{ar a}^0} = left( {{a_0},{a_2},{a_4} ldots ,{a_{n - 2}}} ight)]

    [{{ar a}^1} = left( {{a_1},{a_3},{a_5} ldots ,{a_{n - 1}}} ight)]

    它们对应的方程为:

    [{A^0}left( x ight) = {a_0} + {a_2}x + ?ldots ?+ {a_{n - 2}}{x^{frac{n}{2} - 1}}]

    [{A^1}left( x ight) = {a_1} + {a_3}x + ?ldots ?+ {a_{n - 1}}{x^{frac{n}{2} - 1}}]

    显然

    [Aleft( x ight) = {A^0}left( {{x^2}} ight) + x{A^1}left( {{x^2}} ight) o left[ * ight]]

    对于这两个向量,假设现在我们求出了它们对应的点值表示(注意它们现在是两个最高次数为n/2-1的多项式)

    [{{ar y}^0} = left( {{y_0},{y_1},{y_2} ldots ,{y_{frac{n}{2} - 1}}} ight)]

    [{{ar y}^1} = left( {{y_0},{y_1},{y_2} ldots ,{y_{frac{n}{2} - 1}}} ight)]

    最后,我们由这两个来计算我们最后的答案$ar{y}$.为方便,我们用$ar{y_{i}}$来表示$ar{y}$的第i个元素.

    那么,我们有:

    (1)对于k属于[0,n/2-1],

    [{{ar y}_k} = {{ar y}^0}_k + w_n^k{{ar y}^1}_k]

    证明:

    $ar{y}_{k}^{0}+w_{n}^{k}ar{y}_{k}^{1}$
    $=A^{0}(w_{frac{n}{2}}^{k})+w_{n}^{k}A^{1}(w_{frac{n}{2}}^{k})$
    $=sum_{j=0}^{frac{n}{2}-1}a_{2j}w_{frac{n}{2}}^{kj}+w_{n}^{k}sum_{j=0}^{frac{n}{2}-1}a_{2j+1}w_{frac{n}{2}}^{kj}$
    $=sum_{j=0}^{frac{n}{2}-1}a_{2j}w_{n}^{2kj}+w_{n}^{k}sum_{j=0}^{frac{n}{2}-1}a_{2j+1}w_{n}^{2kj}$
    $=sum_{j=0}^{frac{n}{2}-1}a_{2j}w_{n}^{k(2j)}+sum_{j=0}^{frac{n}{2}-1}a_{2j+1}w_{n}^{k(2j+1)}$
    $=sum_{j=0}^{n-1}a_{j}w_{n}^{kj}=ar{y}_{k}$
    (2)对于k属于[n/2,n-1],

    [{{ar y}_k} = {{ar y}^0}_{k - frac{n}{2}} - w_n^{k - frac{n}{2}}{{ar y}^1}_{k - frac{n}{2}}]

    证明:令k=n/2+t,t属于[0,n/2-1],

    $ar{y}_{k-frac{n}{2}}^{0}+w_{n}^{k-frac{n}{2}}ar{y}_{k-frac{n}{2}}^{1}$
    $=ar{y}_{t}^{0}+w_{n}^{t}ar{y}_{t}^{1}$
    $=A^{0}(w_{frac{n}{2}}^{t})-w_{n}^{t}A^{1}(w_{frac{n}{2}}^{t})$
    $=sum_{j=0}^{frac{n}{2}-1}a_{2j}w_{frac{n}{2}}^{tj}-w_{n}^{t}sum_{j=0}^{frac{n}{2}-1}a_{2j+1}w_{frac{n}{2}}^{tj}$
    $=sum_{j=0}^{frac{n}{2}-1}a_{2j}w_{n}^{2kj}-w_{n}^{t}sum_{j=0}^{frac{n}{2}-1}a_{2j+1}w_{n}^{2tj}$


    因为$w_{n}^{t+frac{n}{2}}=w_{n}^{t}w_{n}^{frac{n}{2}}=-w_{n}^{t}$

    所以上式
    $=sum_{j=0}^{frac{n}{2}-1}a_{2j}w_{n}^{2tj}+w_{n}^{t+frac{n}{2}}sum_{j=0}^{frac{n}{2}-1}a_{2j+1}w_{n}^{2tj}$
    $=sum_{j=0}^{frac{n}{2}-1}a_{2j}w_{n}^{2tj}+sum_{j=0}^{frac{n}{2}-1}a_{2j+1}w_{n}^{2tj+t+frac{n}{2}}$
    $=sum_{j=0}^{frac{n}{2}-1}a_{2j}w_{n}^{2tj+jn}+sum_{j=0}^{frac{n}{2}-1}a_{2j+1}w_{n}^{2tj+jn+t+frac{n}{2}}$
    $=sum_{j=0}^{frac{n}{2}-1}a_{2j}w_{n}^{2j(t+frac{n}{2})}+sum_{j=0}^{frac{n}{2}-1}a_{2j+1}w_{n}^{(2j+1)(t+frac{n}{2})}$
    $=sum_{j=0}^{n-1}a_{j}w_{n}^{(t+frac{n}{2})j}$
    $=sum_{j=0}^{n-1}a_{j}w_{n}^{kj}=ar{y}_{k}$


    到此位置,我们就得到了如何将系数表示法转化成点值表示法的方法。

    我们设现在有一个n*n的矩阵M,其中$M_{ij}=w_{n}^{ij},0leq i,jleq n-1$.那么上述从系数转化到点值的过程可以表示为

    [ar y = M cdot ar a]

    如果我们要从点值变换到系数表示,那么

    [ar a = {M^{ - 1}} cdot ar y]

    我们下面证明M的逆矩阵在(i,j)位置的元素为 $M_{ij}^{ - 1} = frac{{w_n^{ - ij}}}{n}$

    证明:$(M_{-1}M)_{ij}=sum_{k=0}^{n-1}M_{ik}^{-1}M_{kj}=sum_{k=0}^{n-1}frac{w_{n}^{-ik}}{n}w_{n}^{kj}=sum_{k=0}^{n-1}frac{w_{n}^{k(j-i)}}{n}$.如果i=j则值为1;否则由于$-(n-1)<=j-i<=n-1$且j!=i,所以(j-i)不能被n整除,由上面的性质3可以得到这个值为0。 所以这个乘积是单位矩阵,所以我们的命题得证。

    因此,我们只要将$w_{n}$用$w_{n}^{-1}$代替,与从系数变换到点值相同的方法进行运算,最后将每个元素除以n即可。这样就解决了从点值到系数的变换。


    4 最后的反思

    最后,我们思考一下,这个之所以能运用分治,是因为单位根

    [{w_n} = {e^{frac{{2pi i}}{n}}}]

    在乘法意义下是一个群,即它满足$w_{n}^{n} = w_{n}^{0} = 1$

  • 相关阅读:
    redhat安装opencv
    vsftpd的配置与使用
    Redhat 安装编译 Python-2.7.12
    YUM 安装与配置
    docker安装mysql
    高频问题 java8新特性(转载)
    quartz简单实例实现
    java8线程池
    java8多线程不带返回值
    java8多线程带返回值的
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/5998025.html
Copyright © 2011-2022 走看看