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

于是这个题的技巧就是把b数组翻转一下 b_i = b_n - 1 - i (下标从0)

题目就变形为c_k = sigma (a_i * b_n - 1 - i + k) = c_n - 1 + k 于是就上板子了

kuangbin的板子还是很厉害的

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <math.h>
using namespace std;
const double PI = acos(-1.0);

struct Complex
{
double x, y;
Complex(double _x = 0.0, double _y = 0.0)
{
x = _x;
y = _y;
}
Complex operator + (const Complex &b) const
{
return Complex(x + b.x, y + b.y);
}
Complex operator - (const Complex &b) const
{
return Complex(x - b.x, y - b.y);
}
Complex operator * (const Complex &b) const
{
return Complex(x * b.x - y * b.y, x * b.y + y * b.x);
}
};

void change(Complex y[], int len)
{
int i, j, k;
for(i = 1, j = len / 2; i < len - 1; i++)
{
if(i < j) swap(y[i], y[j]);
k = len / 2;
while(j >= k)
{
j -= k;
k /= 2;
}
if(j < k) j += k;
}
}

void fft(Complex y[], int len, int on)
{
change(y, len);
for(int h = 2; h <= len; h <<= 1)
{
Complex wn(cos(-on * 2 * PI / h), sin(-on * 2 * PI / h));
for(int j = 0; j < len; j += h)
{
Complex w(1, 0);
for(int k = j; k < j + h / 2; k++)
{
Complex u = y[k];
Complex t = w * y[k + h / 2];
y[k] = u + t;
y[k + h / 2] = u - t;
w = w * wn;
}
}
}

if(on == -1)
for(int i = 0; i < len; i++)
y[i].x /= len;
}

Complex x1[400005], x2[400005];

int main()
{
int n; scanf("%d", &n);
int nn = n;
for(int i = 0; i < n; i++)
{
double u, v;
scanf("%lf%lf", &u, &v);
x1[i] = Complex(u, 0);
x2[n - i - 1] = Complex(v, 0);
}
n = 2 * n - 1;
int len = 1;
while(len < n) len <<= 1;
for(int i = n; i < len; i++) x1[i] = x2[i] = Complex(0.0, 0.0);

fft(x1, len, 1);
fft(x2, len, 1);
for(int i = 0; i < len; i++) x1[i] = x1[i] * x2[i];
fft(x1, len, -1);

for(int i = nn - 1; i < n; i++) printf("%d\n", (int)(x1[i].x + 0.5));
return 0;
}
View Code

posted @ 2018-07-16 15:59  lwqq3  阅读(146)  评论(0编辑  收藏  举报