BZOJ 2194: 快速傅立叶之二

题目大意:

计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n 。

题解:
把b倒过来,求卷积,
FFT。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define pi acos(-1)
using namespace std;
struct node{
    double x,i;
    node(){}
    node(double x,double i):x(x),i(i){}
    node operator+(node a) {return node(x+a.x,i+a.i);}
    node operator-(node a) {return node(x-a.x,i-a.i);}
    node operator*(node a) {return node(x*a.x-i*a.i,x*a.i+i*a.x);}
}a[300005],b[300005];
int rev[300005];
void fft(node *a,int n,int t)
{
    for (int i=0; i<n; i++)
        if (i<rev[i]) swap(a[i],a[rev[i]]);
    for (int j=1; j<n; j<<=1)
    {
        node wn(cos(2*pi/(j<<1)),t*sin(2*pi/(j<<1)));
        for (int i=0; i<n; i+=(j<<1))
        {
            node w(1,0),t0,t1;
            for (int k=0; k<j; k++,w=w*wn)
            {
                t0=a[i+k];
                t1=w*a[i+j+k];
                a[i+k]=t0+t1;
                a[i+j+k]=t0-t1;
            }
        }
    }
}
int main()
{
   	int n;
	scanf("%d",&n);
	n--;
    for (int i=0; i<=n; i++) scanf("%lf%lf",&a[i].x,&b[n-i].x);
    int nn=1,len=0;
    while (nn<=2*n){
        nn<<=1;
        len++;
    }
    rev[0]=0;
    for (int i=1; i<nn; i++)
        rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1));
    fft(a,nn,1);
    fft(b,nn,1);
    for (int i=0; i<=nn; i++)
        a[i]=a[i]*b[i];
    fft(a,nn,-1);
    for (int i=n; i<=2*n; i++)
        printf("%d\n",(int)(a[i].x/nn+0.5));
    return 0;
}

  

 

 

 

posted @ 2018-04-11 15:27  ~Silent  阅读(155)  评论(0编辑  收藏  举报
Live2D