FFT 优化多项式乘法的模板
提交地址http://uoj.ac/problem/34
#include<bits/stdc++.h>
using namespace std;
#define PI (acos(-1.0))
typedef complex<double> comp;
void change(comp y[], int ln)
{
for (int i = 1, j = ln >> 1;i < ln - 1;++i)
{
if (i < j)swap(y[i], y[j]);
int k = ln >> 1;
while (j >= k)
{
j -= k;
k >>= 1;
}
if (j < k)j += k;
}
} /** /
/*
type=1 DFT
type=-1 IDFT
*/
void FFT(comp y[], int ln, int type)
{
change(y, ln);
for (int h = 2;h <= ln;h <<= 1)
{
comp wn = comp(cos(type * 2 * PI / h), sin(type * 2 * PI / h));
for (int j = 0;j < ln;j += h)
{
comp w(1, 0);
for (int k = j;k < j + (h >> 1);k++)
{
comp u = y[k];
comp t = w*y[k + (h >> 1)];
y[k] = u + t;
y[k + (h >> 1)] = u - t;
w *= wn;
}
}
}
if (type == -1)
{
for (int i = 0;i < ln;i++)
{
double img = imag(y[i]);
double rel = real(y[i]);
rel /= ln;
y[i] = comp(rel, img);
}
}
}
const int MAXN = 400005;
comp x1[MAXN], x2[MAXN];
int s1[MAXN], s2[MAXN];
int sum[MAXN];
int main()
{
int t;
memset(sum, 0, sizeof(sum));
int ln1, ln2;
scanf("%d %d", &ln1, &ln2);
ln1++;
ln2++;
for (int i = 0;i < ln1;i++) scanf("%d", s1 + i);
for (int i = 0;i < ln2;i++) scanf("%d", s2 + i);
int ln = 1;
while ((ln < (ln1 << 1)) || (ln < (ln2 << 1)))ln <<= 1;
for (int i = 0;i < ln1;i++)x1[i] = comp(s1[ln1 - i - 1],0);
for (int i = ln1;i < ln;i++)x1[i] = comp(0, 0);
for (int i = 0;i < ln2;i++)x2[i] = comp(s2[ln2 - i - 1], 0);
for (int i = ln2;i < ln;i++)x2[i] = comp(0, 0);
FFT(x1, ln, 1);
FFT(x2, ln, 1);
for (int i = 0;i < ln;i++)x1[i] *= x2[i];
FFT(x1, ln, -1);
for (int i = 0;i < ln;i++)sum[i] = (real(x1[i]) + 0.5);
ln = ln1+ln2-2;
for (int i = ln;i>=0;i--)
{
printf("%d ", sum[i]);
}
putchar('\n');
}