Problem
数据范围:
1
≤
n
≤
50000
1≤n≤50000
1≤n≤50000,
1
≤
m
≤
100
1≤m≤100
1≤m≤100,
1
≤
a
i
≤
m
1≤a_i≤m
1≤ai≤m。
Solution
我们的目标是最小化这个式子:
∑ i = 1 n ( x i − y i + c ) 2 \sum_{i=1}^n(x_i-y_i+c)^2 i=1∑n(xi−yi+c)2
把它拆开就是:
∑ i = 1 n ( x i 2 + y i 2 − 2 x i y i + c 2 + 2 c ( x i − y i ) ) \sum_{i=1}^n(x_i^2+y_i^2-2x_iy_i+c^2+2c(x_i-y_i)) i=1∑n(xi2+yi2−2xiyi+c2+2c(xi−yi))
那么我们的答案就可以分成三个部分:
- ∑ i = 1 n ( x i 2 + y i 2 ) \sum_{i=1}^n(x_i^2+y_i^2) ∑i=1n(xi2+yi2),记为 A,这显然是一个定值,可以直接计算。
- ∑ i = 1 n ( c 2 + 2 c ( x i − y i ) ) \sum_{i=1}^n(c^2+2c(x_i-y_i)) ∑i=1n(c2+2c(xi−yi)),记为 B,由于 ∑ i = 1 n ( x i − y i ) \sum_{i=1}^n(x_i-y_i) ∑i=1n(xi−yi) 是定值,那就可以把它看成关于 c c c 的二次函数,取对称轴附近的几个点(因为 c c c 必须是整数,而对称轴不一定是整数)更新答案即可。
- 2 ∑ i = 1 n x i y i 2\sum_{i=1}^nx_iy_i 2∑i=1nxiyi,记为 C,我们要最大化这个式子。那么将 x x x 翻转,将 y y y 倍长,就是一个卷积的形式了。用 f f t fft fft 解出来,不难发现,对于 ∀ k ∈ [ n + 1 , 2 n ] \forall k\in[n+1,2n] ∀k∈[n+1,2n],该位置上的值为 ∑ i = 1 n x i × y k − i + 1 \sum_{i=1}^nx_{i}\times y_{k-i+1} ∑i=1nxi×yk−i+1,这就相当于是旋转,取 m a x max max 就可以了。
可以自己在草稿纸上推一推,更助于自己理解。
Code
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 500005
#define ll long long
using namespace std;
int n,m,limit=1,pos[N];
const double pi=acos(-1);
struct complex{
double x,y;
complex(){}
complex(double x,double y):x(x),y(y){}
friend complex operator+(const complex &a,const complex &b) {return complex(a.x+b.x,a.y+b.y);}
friend complex operator-(const complex &a,const complex &b) {return complex(a.x-b.x,a.y-b.y);}
friend 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);}
friend complex operator/(const complex &a,double b) {return complex(a.x/b,a.y/b);}
}a[N],b[N];
int x[N],y[N];
void prework(){
while(limit<=(n<<2)) limit<<=1;
for(int i=0;i<limit;++i)
pos[i]=(pos[i>>1]>>1)|((i&1)*(limit>>1));
}
void DFT(complex f[],int type){
for(int i=0;i<limit;++i)
if(pos[i]>i) swap(f[i],f[pos[i]]);
for(int mid=1;mid<limit;mid<<=1){
complex now=complex(cos(pi/mid),type*sin(pi/mid));
for(int i=0;i<limit;i+=(mid<<1)){
complex w=complex(1,0);
for(int j=0;j<mid;++j,w=w*now){
complex p0=f[i+j],p1=w*f[i+j+mid];
f[i+j]=p0+p1,f[i+j+mid]=p0-p1;
}
}
}
if(type==-1) for(int i=0;i<limit;++i) f[i].x/=limit;
}
int main(){
ll A=0,B=0,sum=0;
scanf("%d%d",&n,&m),prework();
for(int i=1;i<=n;++i) scanf("%lf",&a[i].x);
for(int i=1;i<=n;++i) scanf("%lf",&b[i].x),b[n+i]=b[i];
for(int i=1;i<=n;++i) A+=a[i].x*a[i].x+b[i].x*b[i].x,sum+=a[i].x-b[i].x;
reverse(a+1,a+n+1);
ll axis=-sum/n,C=1e18;
for(int i=-1;i<=1;++i) C=min(C,n*(axis+i)*(axis+i)+2*(axis+i)*sum);
DFT(a,1),DFT(b,1);
for(int i=0;i<limit;++i) a[i]=a[i]*b[i];
DFT(a,-1);
for(int i=1;i<=n;++i)
B=max(B,(ll)(a[n+i].x+0.5));
printf("%lld\n",A+C-2*B);
return 0;
}