b数组倒过来就是卷积了。
#include <cstdio>
#include <complex>
#include <cmath>
#define rep(i,j,k) for(i=j;i<k;++i)
using namespace std;
typedef complex<double> cd;
const double PI = acos(-1.);
const int N = 500010;
cd a[N], b[N];
int rev[N];
void fft(cd a[], int n, int ratio) {
int m, j, k;
rep(j,0,n) if (j < rev[j]) swap(a[j], a[rev[j]]);
for (m = 2; m <= n; m *= 2) {
cd wm(cos(2 * PI / m), sin(ratio * 2 * PI / m));
for (k = 0; k < n; k += m) {
cd w(1, 0);
rep(j, k, k + m / 2) {
cd u = a[j], t = w * a[j + m / 2];
a[j] = u + t;
a[j + m / 2] = u - t;
w *= wm;
}
}
}
if (ratio == -1) rep(j,0,n) a[j] /= n;
}
int main() {
int n, m, i, k;
double x, y;
scanf("%d", &m);
rep(i,0,m) {
scanf("%lf%lf", &x, &y);
a[i] = x; b[m - i - 1] = y;
}
n = 1; k = -1;
while (n < 2 * m - 1) n *= 2, ++k;
rep(i,0,n) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << k);
fft(a, n, 1); fft(b, n, 1);
rep(i,0,n) a[i] *= b[i];
fft(a, n, -1);
rep(i,m-1,m+m-1) printf("%d\n", (int)(a[i].real() + 0.1));
return 0;
}
2194: 快速傅立叶之二
Description
请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5。 a,b中的元素均为小于等于100的非负整数。
Input
第一行一个整数N,接下来N行,第i+2..i+N-1行,每行两个数,依次表示a[i],b[i] (0 < = i < N)。
Output
输出N行,每行一个整数,第i行输出C[i-1]。
Sample Input
5
3 1
2 4
1 1
2 4
1 4
Sample Output
24
12
10
6
1