BZOJ.2194. Fast Fourier II (FFT Convolution)

topic link

\(Descripton\)
  Given \(A[\ ],B[\ ]\) , find \[C[k]=\sum_{i=k}^{n-1}A[i]*B[ik ]\ (0\leq k<n)\]
\(Solution\)
  (Shilling \(n=n-1\) )
  First think about convolution. .
  The difference between \(i\) and \(ik\) is certain, but the form of convolution is \[C[k]=\sum_{i=1}^k A[i]*B[ki]\ ]
  That is , the sum of \(i\) and \(ki\) is certain.
  So consider reversing an array, here reversing \(B[\ ]\) , then \[C[k]=\sum_{i=k}^n A[i]*B[n+ki] \]
In   this way , the sum of \(i\) and \(n+ki\) is certain, which is \(n+k\) , so let \[D[n+k]=\sum_{i=k} ^n A[i]*B[n+ki]\]
  This way you can \(FFT\) find \(D[\ ]\).
  \[D[n+k]=\sum_{i=0}^{n+k}A[i]*B[n+ki]\]
  \(i=0\sim k-1\) and \( When i=n+1\sim n+k\) , either \(A[i]=0\) or \(B[i]=0\) , no effect.
  So the final \(C[k]=D[n+k]\) .

//13148kb   1544ms
#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=263000;//2^{18}=262144 > 2*1e5
const double PI=acos(-1);

int n;
struct Complex
{
    double x,y;
    Complex() {}
    Complex(double x,double y):x(x),y(y) {}
    Complex operator + (const Complex &a)const{
        return Complex(x+a.x, y+a.y);
    }
    Complex operator - (const Complex &a)const{
        return Complex(x-a.x, y-a.y);
    }
    Complex operator * (const Complex &a)const{
        return Complex(x*a.x-y*a.y, x*a.y+y*a.x);
    }
}A[N],B[N],D[N];

inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}
void FFT(Complex *a,int lim,int opt)
{
    for(int i=0,j=0; i<lim; ++i)
    {
        if(i>j) std::swap(a[i],a[j]);
        for(int l=lim>>1; (j^=l)<l; l>>=1);
    }
    for(int i=2; i<=lim; i<<=1)
    {
        int mid=i>>1;
        Complex Wn(cos(2.0*PI/i),opt*sin(2.0*PI/i)),t;
        for(int j=0; j<lim; j+=i)
        {
            Complex w(1,0);
            for(int k=0; k<mid; ++k,w=w*Wn)
                a[j+mid+k]=a[j+k]-(t=w*a[j+mid+k]),
                a[j+k]=a[j+k]+t;
        }
    }
}

int main()
{
    n=read()-1;
    for(int i=0; i<=n; ++i) A[i].x=read(),B[n-i].x=read();
    int lim=1;
    while(lim <= n<<1) lim<<=1;
    FFT(A,lim,1), FFT(B,lim,1);
    for(int i=0; i<lim; ++i) A[i]=A[i]*B[i];
    FFT(A,lim,-1);
    for(int i=0; i<=n; ++i) printf("%d\n",(int)(A[i+n].x/lim+0.5));

    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325258982&siteId=291194637