# 「BZOJ2194」快速傅立叶之二

## Input

第一行一个整数N,接下来N行，第i+2..i+N-1行，每行两个数，依次表示a[i],b[i] (0 < = i < N)。

5
3 1
2 4
1 1
2 4
1 4

## Sample Output

24
12
10
6
1

初看题目所要求的式子，很像卷积， f(x) * g(x) = sigma(f(x) g(t-x))  那么我们只要将 b数组变换一下即可， 另 d[i] = b[n-i-1] ， 则a[i]*b[k-i] = a[i]*b[n-1-(n+k-i-1)] = a[i]*d[n+k-1-i] ( k-1 < i < n) 这不就是一个标准的卷积了吗，fft 即可

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 3e5+5;
const double pi = acos(-1.0);

int n;
struct Complex{
double x, y;
Complex (double _x=0, double _y=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);
}
};
Complex x1[maxn], x2[maxn];
void change(Complex y[], int len){
for(int i = 1, j = len/2; i < len-1; i++){
if (i < j) swap(y[i], y[j]);
int 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;
}
}

int main () {

cin >> n;
for(int i = 0; i < n; i++) scanf("%lf%lf", &x1[i].x, &x2[n-i-1].x);
int len = 1;
while(len < 2*n) len <<= 1;

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 = n-1; i < 2*n-1; i++){
int x = (int)(x1[i].x+0.5);
printf("%d\n", x);
}
return 0;
}


posted @ 2018-08-22 14:21  楼主好菜啊  阅读(162)  评论(0编辑  收藏  举报