zoukankan      html  css  js  c++  java
  • bluestein算法

    我们熟知的FFT算法实际上是将一个多项式在2n个单位根处展开,将其点值对应相乘,并进行逆变换。然而,由于单位根具有“旋转”的特征(即$w_{m}^{j}=w_{m}^{j+m}$),若多项式次数大于二分之长度,FFT将进行一次长度为2n的循环卷积。bluestein的算法是解决了在任意长度上的循环卷积问题。

    我们知道,任何一个n次多项式都可以被n+1个点值进行表示,因此如果我们选取所有形如$w_{n+1}^{i}$的单位根并带入多项式,进行类似于FFT的变化(这里没有证明),理应得到正确的结果。

    设多项式A为$sum_{i=0}^{n}{a_i*x^i}$,$F_k$为$A(w_{n+1}^{k})$,则$F_k=sum_{i=0}^{n}{a_i*w_{n+1}^{ik}}$

    考虑ik的另外一种组合含义,即有两个盒子,每个盒子分别有i个球和k个球,求有多少种拿出两个球且分别属于两个盒子的方法,因此$ik= binom{i+k}{2}- binom{i}{2}- binom{k}{2}$。它的意义在下面推导中可见。

    因此$F_k=sum_{i=0}^{n}{a_i*w_{n+1}^{ binom{i+k}{2}- binom{i}{2}- binom{k}{2}}}=w_{n+1}^{- binom{k}{2}}sum_{i=0}^{n}{a_i*w_{n+1}^{- binom{i}{2}}*w_{n+1}^{ binom{i+k}{2}}}$

    注意到(i+k)-(i)=k,令$A_{-i}=a_i*w_{n+1}^{- binom{i}{2}}$,$B_i=w_{n+1}^{ binom{i}{2}}$。因此,A和B的卷积的第k项即为$frac{F_k}{w_{n+1}^{- binom{k}{2}}}$。由于A的下标为负数,我们将A的下标集体加上n。于是,一次bluestein操作花了三次长度为4n的FFT操作。

    将多项式转化为点值表达后,我们依葫芦画瓢地将对应位置相乘、进行相应的逆变换(即取单位根的共轭)。而此部分正确性的证明过程是与FFT类似的。

    例题:poj2821。对于循环卷积B=A*C,求C。

     1 #include<cstdio>
     2 #include<math.h>
     3 #include<cstring>
     4 #include<iomanip>
     5 using namespace std;
     6 typedef long long int ll;
     7 typedef double ld;
     8 const int maxn=(1<<19)+5;
     9 const ld pi=acos(-1);
    10 struct com
    11 {
    12     ld x,y;
    13     com(ld a=0,ld b=0):x(a),y(b){}
    14     com operator+(const com&A){return com(x+A.x,y+A.y);}
    15     com operator-(const com&A){return com(x-A.x,y-A.y);}
    16     com operator*(const com&A){return com(x*A.x-y*A.y,x*A.y+y*A.x);}
    17     com operator/(const ld&d){return com(x/d,y/d);}
    18     com operator/(const com&A){return com(x,y)*com(A.x,-A.y)/(A.x*A.x+A.y*A.y);}
    19 }A[maxn],B[maxn];
    20 int r[maxn];
    21 inline void DFT(com*A,int limit,int type)
    22 {
    23     for(int i=1;i<limit;++i)
    24     {
    25         r[i]=(r[i>>1]>>1)|((i&1)?(limit>>1):0);
    26         if(i<r[i])
    27             swap(A[i],A[r[i]]);
    28     }
    29     for(int len=2;len<=limit;len<<=1)
    30     {
    31         com d(cos(pi*2/len),sin(pi*2/len)*type);
    32         for(int i=0;i<limit;i+=len)
    33         {
    34             com w(1,0);
    35             for(int j=0,p1=i,p2=i+len/2;j<len/2;++j,++p1,++p2)
    36             {
    37                 com x=A[p1],y=A[p2]*w;
    38                 A[p1]=x+y;
    39                 A[p2]=x-y;
    40                 w=w*d;
    41             }
    42         }
    43     }
    44 }
    45 com tmp1[maxn],tmp2[maxn];
    46 inline com get(int k,int n,int type)
    47 {
    48     ll g=(ll)k*(k-1)/2;
    49     return com(cos(pi*2/(n+1)*g),sin(pi*2/(n+1)*g)*type);
    50 }
    51 inline void bluestein(com*A,int n,int type)
    52 {
    53     int limit=1;
    54     while(limit<4*n+1)
    55         limit<<=1;
    56     for(int i=0;i<limit;++i)
    57         tmp1[i]=tmp2[i]=com(0,0);
    58     for(int i=0;i<=n;++i)
    59         tmp1[n-i]=A[i]*get(i,n,-type);
    60     for(int i=0;i<=n*2;++i)
    61         tmp2[i]=get(i,n,type);
    62     DFT(tmp1,limit,1);
    63     DFT(tmp2,limit,1);
    64     for(int i=0;i<limit;++i)
    65         tmp1[i]=tmp1[i]*tmp2[i];
    66     DFT(tmp1,limit,-1);
    67     for(int i=0;i<=n;++i)
    68         A[i]=tmp1[i+n]/limit*get(i,n,-type);
    69 }
    70 int n;
    71 int main()
    72 {
    73     scanf("%d",&n);
    74     --n;
    75     for(int i=0;i<=n;++i)
    76         scanf("%lf",&A[i].x);
    77     for(int i=0;i<=n;++i)
    78         scanf("%lf",&B[i].x);
    79     bluestein(A,n,1);
    80     bluestein(B,n,1);
    81     for(int i=0;i<=n;++i)
    82         A[i]=B[i]/A[i];
    83     bluestein(A,n,-1);
    84     for(int i=0;i<=n;++i)
    85         A[i].x/=(n+1);
    86     for(int i=0;i<=n;++i)
    87         printf("%.4f
    ",A[i].x);
    88     return 0;
    89 }
    View Code
  • 相关阅读:
    第19篇-Kibana对Elasticsearch的实用介绍
    第18篇-用ElasticSearch索引MongoDB,一个简单的自动完成索引项目
    第17篇-使用Python的初学者Elasticsearch教程
    第16篇-关于Elasticsearch的6件不太明显的事情
    第15篇-使用Django进行ElasticSearch的简单方法
    第14篇-Python中的Elasticsearch入门
    第13篇-Elasticsearch查询-术语级查询
    第12篇-Elasticsearch全文查询
    MQTT
    rest-framework-@action()装饰器
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/14427244.html
Copyright © 2011-2022 走看看