bzoj 4827: [Hnoi2017]礼物 [fft]

4827: [Hnoi2017]礼物

题意:略


以前做的了

化一化式子就是一个卷积和一些常数项

我记着确定调整值还要求一下导...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = (1<<18)+5, INF=1e9+5;
const double PI = acos(-1.0);
inline int read() {
	char c=getchar(); int x=0,f=1;
	while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
	while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
	return x*f;
}

struct meow {
	double x, y;
	meow(double a=0, double b=0) : x(a), y(b) {}
};
meow operator + (meow a, meow b) {return meow(a.x + b.x, a.y + b.y);}
meow operator - (meow a, meow b) {return meow(a.x - b.x, a.y - b.y);}
meow operator * (meow a, meow b) {return meow(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);}
meow conj(meow a) {return meow(a.x, -a.y);}
typedef meow cd;
namespace fft {
	int n, rev[N];
	cd omega[N], omegaInv[N];
	void init(int lim) {
		n=1; int k=0; while(n<lim) n<<=1, k++;
		for(int i=0; i<n; i++) rev[i] = (rev[i>>1]>>1) | ((i&1)<<(k-1));
		for(int i=0; i<n; i++) {
			omega[i] = cd(cos(2*PI/n*i), sin(2*PI/n*i));
			omegaInv[i] = conj(omega[i]);
		}
	}

	void dft(cd *a, int flag) {
		cd *w = flag > 0 ? omega : omegaInv;
		for(int i=0; i<n; i++) if(i < rev[i]) swap(a[i], a[rev[i]]);
		for(int l=2; l<=n; l<<=1) {
			int m = l>>1;
			for(cd *p=a; p!=a+n; p+=l) 
				for(int k=0; k<m; k++) {
					cd t = w[n/l*k] * p[k+m];
					p[k+m] = p[k] - t;
					p[k] = p[k] + t;
				}
		}
		if(flag == -1) for(int i=0; i<n; i++) a[i].x /= n;
	}

	void mul(cd *a, cd *b) {
		dft(a, 1); dft(b, 1);
		for(int i=0; i<n; i++) a[i] = a[i] * b[i];
		dft(a, -1);
	}
}

int n, m, x[N], y[N]; ll ans, sum, t;
cd a[N], b[N]; 
int main() {
	freopen("in", "r", stdin);
	n=read(); m=read();
	for(int i=1; i<=n; i++) a[i].x = x[i] = read(), ans += x[i] * x[i];
	for(int i=1; i<=n; i++) b[n-i+1].x = b[n-i+1+n].x = y[i] = read(), ans += y[i] * y[i], sum += x[i] - y[i];
	sum = abs(sum);
	ll c = floor((double) sum / n + 0.5); //printf("c %lld\n", c);
	ans += c * (n * c - 2 * sum);
	
	//printf("ans %lld\n", ans);
	fft::init(n+n+1); 
	fft::mul(a, b);
	for(int i=n+1; i<=n+n; i++) t = max(t, (ll)floor(a[i].x + 0.5));// printf("a %d  %lf\n", i, a[i].x);
	t *= 2;
	//printf("t %lld\n", t);
	printf("%lld", ans - t);
}

posted @ 2017-04-24 11:30  Candy?  阅读(281)  评论(0编辑  收藏  举报