bzoj4827 Hnoi2017 礼物
solution
将式子展开
\[\sum\limits_{i=1}^n(x_i - y_i + c)^2
\]
\[=\sum\limits_{i=1}^nx_i^2+y_i^2-2x_iy_i+2c(x_i-y_i)+c^2
\]
\[=\sum\limits_{i=1}^nx_i^2+\sum\limits_{i=1}^ny_i^2-2\sum\limits_{i=1}^nx_iy_i+2c(\sum\limits_{i=1}^nx_i-\sum\limits_{i=1}^ny_i)+nc^2
\]
前面\(\sum\limits_{i=1}^nx_i^2+\sum\limits_{i=1}^ny_i^2\)是定值。
后面\(2c(\sum\limits_{i=1}^nx_i-\sum\limits_{i=1}^ny_i)+nc^2\)是个二次函数。最值很好求。
所以问题就是要最大化\(\sum\limits_{i=1}^nx_iy_i\),
我们设将\(y\)这个手环左移了\(k\)下。那么答案就变为\(\sum\limits_{i=1}^nx_iy_{i+k}\)。
将x序列倒过来就变成了卷积的形式\(\sum\limits_{i=1}^nx_{n-i}y_{i+k}\)。
code
/*
* @Author: wxyww
* @Date: 2019-07-21 20:49:19
* @Last Modified time: 2019-07-21 21:33:06
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
#include<cmath>
using namespace std;
typedef long long ll;
const int N = 1000000 + 100;
ll read() {
ll x=0,f=1;char c=getchar();
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;
}
int Re[N],n,m,limit = 1;
struct complex {
double x,y;
complex(double xx = 0,double yy = 0) {x = xx;y = yy;}
}a[N],b[N];
complex operator + (const complex &A,const complex &B) {
return complex(A.x + B.x,A.y + B.y);
}
complex operator - (const complex &A,const complex &B) {
return complex(A.x - B.x,A.y - B.y);
}
complex operator * (const complex &A,const complex &B) {
return complex(A.x * B.x - A.y * B.y,A.x * B.y + A.y * B.x);
}
double ans;
double T;
const double pi = acos(-1.0);
void FFT(complex *A,int type) {
for(int i = 0;i < limit;++i) if(i < Re[i]) swap(A[i],A[Re[i]]);
for(int mid = 1;mid < limit;mid <<= 1) {
complex Wn(cos(pi / mid),type * sin(pi / mid));
for(int R = mid << 1,j = 0;j < limit;j += R) {
complex w(1.0,0);
for(int k = 0;k < mid;++k,w = w * Wn) {
complex x = A[j + k],y = w * A[j + mid + k];
A[j + mid + k] = x - y;
A[j + k] = x + y;
}
}
}
}
ll calc(ll x) {
return n * x * x + 2 * T * x;
}
int main() {
n = read(),m = read();
for(int i = 0;i < n;++i) {
int x = read();
a[n - i].x = x;
ans += x * x;
T += x;
}
for(int i = 0;i < n;++i) {
int y = read();
b[i].x = b[i + n].x = y;
ans += y * y;
T -= y;
}
int num = 0;
while(limit <= n * 3) limit <<= 1,num++;
for(int i = 0;i <= limit;++i) Re[i] = Re[i >> 1] >> 1 | ((i & 1) << (num - 1));
FFT(a,1);
FFT(b,1);
for(int i = 0;i <= limit;++i) a[i] = a[i] * b[i];
FFT(a,-1);
double ret = 0;
for(int i = 0;i <= limit;++i) ret = max(ret,round(a[i].x / limit));
ans -= 2 * ret;
ans += calc(round(-T / n));
printf("%.0lf",ans);
return 0;
}
===================================================================================
该怎麼去形容为思念酝酿的痛
夜空霓虹都是我不要的繁荣 ===================================================================================