# BZOJ2194:快速傅立叶之二(FFT)

5
3 1
2 4
1 1
2 4
1 4

24
12
10
6
1

## Solution

QvQ我FFT也就能打个板子了

$C(k)=\sum^{n-1}_{i=k}A_{i}B_{i-k}$一开始我们发现初始式子并不是FFT的形式没法搞

$C(k)=\sum^{n-1}_{i=k}A_{i}B_{n-1-i+k}$然后我们就将B数组翻转过来，然后发现下标和一定了……

$D(n-1+k)=\sum^{n-1}_{i=k}A_{i}B_{n-1-i+k}$然后把式子用另一个D表示出来，然后就可以FFT了……

## Code

 1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #include<cmath>
5 #define N (400000+100)
6 using namespace std;
7
8 double pi=acos(-1.0);
9 int n,fn,l,r[N];
10 struct complex
11 {
12     double x,y;
13     complex (double xx=0,double yy=0)
14     {
15         x=xx; y=yy;
16     }
17 }a[N],b[N];
18
19 complex operator + (complex a,complex b){return complex(a.x+b.x,a.y+b.y);}
20 complex operator - (complex a,complex b){return complex(a.x-b.x,a.y-b.y);}
21 complex operator * (complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
22 complex operator / (complex a,double b){return complex(a.x/b,a.y/b);}
23
24 void FFT(int n,complex *a,int opt)
25 {
26     for (int i=0; i<n; ++i)
27         if (i<r[i])
28             swap(a[i],a[r[i]]);
29     for (int k=1; k<n; k<<=1)
30     {
31         complex wn=complex(cos(pi/k),opt*sin(pi/k));
32         for (int i=0; i<n; i+=(k<<1))
33         {
34             complex w=complex(1,0);
35             for (int j=0; j<k; ++j,w=w*wn)
36             {
37                 complex x=a[i+j], y=w*a[i+j+k];
38                 a[i+j]=x+y; a[i+j+k]=x-y;
39             }
40         }
41     }
42     if (opt==-1) for (int i=0; i<n; ++i) a[i]=a[i]/n;
43 }
44
45 int main()
46 {
47     scanf("%d",&n); n--;
48     for (int i=0; i<=n; ++i)
49         scanf("%lf%lf",&a[i].x,&b[n-i].x);
50     fn=1;
51     while (fn<=n+n) fn<<=1, l++;
52     for (int i=0; i<fn; ++i)
53         r[i]=(r[i>>1]>>1) | ((i&1)<<(l-1));
54     FFT(fn,a,1); FFT(fn,b,1);
55     for (int i=0; i<=fn; ++i)
56         a[i]=a[i]*b[i];
57     FFT(fn,a,-1);
58     for (int i=n; i<=n+n; ++i)
59         printf("%d\n",(int)(a[i].x+0.5));
60 }
posted @ 2018-04-13 20:30  Refun  阅读(129)  评论(-1编辑  收藏  举报