您的位置:首页 > 其它

bzoj 4827: [Hnoi2017]礼物 [fft]

2017-04-24 11:30 375 查看

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
;
cd omega
, omegaInv
;
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
, y
; ll ans, sum, t;
cd a
, b
;
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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: