【BZOJ 2194】快速傅立叶之二

随便代换一下把它变成多项式乘法,及$C[T]=\sum_{i=0}^{T}A[i]×B[T-i]$这种形式,然后FFT求一下就可以啦

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define read(x) x=getint()
using namespace std;
const int N = 400003;
const double Pi = acos(- 1.0);
int getint() {
	int k = 0, fh = 1; char c = getchar();
	for(; c < '0' || c > '9'; c = getchar())
		if (c == '-') fh = -1;
	for(; c >= '0' && c <= '9'; c = getchar())
		k = k * 10 + c - '0';
	return k * fh;
}
struct cp {
	double r, i;
	cp (double _r = 0.0, double _i = 0.0) : r(_r), i(_i) {}
	cp operator + (const cp &x) {return cp(r + x.r, i + x.i);}
	cp operator - (const cp &x) {return cp(r - x.r, i - x.i);}
	cp operator * (const cp &x) {return cp(r * x.r - i * x.i, r * x.i + i * x.r);}
};
cp A[N], u, t;
int rev[N];
void DFT(cp *a, int n, int flag) {
	for(int i = 0; i < n; ++i) A[rev[i]] = a[i];
	for(int i = 0; i < n; ++i) a[i] = A[i];
	for(int m = 2; m <= n; m <<= 1) {
		cp wn(cos(2.0 * Pi / m * flag), sin(2.0 * Pi / m * flag));
		int mid = m >> 1;
		for(int i = 0; i < n; i += m) {
			cp w(1.0);
			for(int j = 0; j < mid; ++j) {
				u = a[i + j], t = a[i + j + mid] * w;
				a[i + j] = u + t;
				a[i + j + mid] = u - t;
				w = w * wn;
			}
		}
	}
	if (flag == -1)
		for(int i = 0; i < n; ++i)
			a[i].r /= n;
}
void init(int &n) {
	int k = 1, ret, L = 0;
	for(; k < n; k <<= 1, ++L);
	n = k;
	for(int i = 0; i < n; ++i) {
		k = i; ret = 0;
		for(int j = 0; j < L; ++j)
			ret <<= 1, ret |= k & 1, k >>= 1;
		rev[i] = ret;
	}
}
void FFT(int *a, int *b, int *c, int la, int lb) {
	static cp x[N], y[N];
	int len = la + lb - 1;
	init(len);
	for(int i = 0; i < len; ++i)
		x[i].r = a[i], x[i].i = 0;
	for(int i = 0; i < len; ++i)
		y[i].r = b[i], y[i].i = 0;
	DFT(x, len, 1); DFT(y, len, 1);
	for(int i = 0; i < len; ++i)
		x[i] = x[i] * y[i];
	DFT(x, len, -1);
	for(int i = 0; i < len; ++i)
		c[i] = (int) (x[i].r + 0.5);
}
int x[N], y[N], a[N], n;
int main() {
	read(n);
	for(int i = 0; i < n; ++i)
		read(x[i]), read(y[i]);
	for(int i = 0; i < n; ++i)
		a[i] = x[n - i - 1];
	FFT(y, a, x, n, n);
	for(int i = 0; i < n; ++i)
		a[i] = x[n - i - 1];
	for(int i = 0; i < n; ++i)
		printf("%d\n", a[i]);
	return 0;
}

233

posted @ 2016-04-25 20:10  abclzr  阅读(224)  评论(0编辑  收藏  举报