bzoj千题计划256:bzoj2194: 快速傅立叶之二

http://www.lydsy.com/JudgeOnline/problem.php?id=2194

 

相乘两项的下标 的 差相同

那么把某一个反过来就是卷积形式

fft优化

 

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

const int N=(1<<18)+2;

const double pi=acos(-1);

int r[N];

struct Complex
{
    double a,b;

    Complex(double x_=0,double y_=0):a(x_),b(y_) {}

    Complex operator + (Complex p)
    {
        Complex c;
        c.a=a+p.a;
        c.b=b+p.b;
        return c;
    }
    
    Complex operator - (Complex p)
    {
        Complex c;
        c.a=a-p.a;
        c.b=b-p.b;
        return c;
    }

    Complex operator * (Complex p)
    {
        Complex c;
        c.a=a*p.a-b*p.b;
        c.b=a*p.b+b*p.a;
        return c;
    }
};

typedef Complex E;
E A[N],B[N],C[N];

int n;

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}

void fft(E *a,int f)
{
    for(int i=0;i<n;++i)
        if(i<r[i]) swap(a[i],a[r[i]]);
    for(int i=1;i<n;i<<=1)
    {
        E wn(cos(pi/i),f*sin(pi/i));
        for(int p=i<<1,j=0;j<n;j+=p)
        {
            E w(1,0);
            for(int k=0;k<i;++k,w=w*wn)
            {
                E x=a[j+k],y=w*a[j+k+i];
                a[j+k]=x+y; a[j+k+i]=x-y;
            }
        }
    }
}

int main()
{
    int cnt;
    read(cnt);
    int x,y;
    for(int i=0;i<cnt;++i)
    {
        read(x); read(y);
        A[cnt-1-i].a=x;
        B[i].a=y;
    }
    int m=cnt+cnt-2,l=0;
    for(n=1;n<=m;n<<=1) l++;
    for(int i=0;i<n;++i) r[i]=(r[i>>1]>>1)|((i&1)<<l-1);
    fft(A,1);
    fft(B,1);
    for(int i=0;i<n;++i) C[i]=A[i]*B[i];
    fft(C,-1);
    for(int i=cnt-1;i>=0;--i) printf("%d\n",int(C[i].a/n+0.5));
}            

 

posted @ 2018-03-03 21:58  TRTTG  阅读(203)  评论(0编辑  收藏  举报