可以发现,(ai+t)-bi和ai-(bi+t)可以表示为ai-bi+x(x in [-m,m])。
对于一对: (ai+x-bi)2==ai2+bi^2+x2+2(ai-bi)x-2aibi
再求和 sum (ai+x-bi)2=sum(ai2)+sum(bi2)+nx2+2x(sum(ai)-sum(bi))-2sum(aibi)
观察,在x一定的情形之下,要这个和尽量小,就要最大化sum(aibi)。
令ci=a[n-i+1], 倍长c(变旋转为滑动),sum(aibi)=sum(c[n-i+1]bi),可以利用卷积的形式:如令C(x)=sum(ci(x^i)), B(x)=sum(bi(x^i)),令D(x)=C(x)B(x),
可知,D(x)的n+p次方项的系数为sum(c[n-i+p]*bi)=sum(a[i+1-p]bi)(a[-n+1,...,0]=a[1,n]),找到D(x)的n+p次方项的系数的最大值。
计算卷积时套上FFT。
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
const double Pi=acos(-1);
struct cplx {
double x,y;
cplx(double x=0,double y=0):x(x),y(y){}
cplx operator+(const cplx& d) {return cplx(x+d.x,y+d.y);}
cplx operator-(const cplx& d) {return cplx(x-d.x,y-d.y);}
cplx operator*(const cplx& d) {return cplx(x*d.x-y*d.y,x*d.y+y*d.x);}
} A[N],B[N];
int lmt,l,r[N];
void fastFourierTrans(cplx*a,int type) {
for(int i=0; i<lmt; ++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int k=1; k<lmt; k<<=1) {
for(int i=0; i<lmt; i+=(k<<1)) {
cplx e(1,0), d(cos(Pi/k),type*sin(Pi/k));
for(int j=0; j<k; j++, e=e*d) {
cplx t=e*a[i+j+k];
a[i+j+k]=a[i+j]-t;
a[i+j] =a[i+j]+t;
}
}
}
}
int n,m;
double a[N],b[N],c[N];
double sqs,sco,dif,ans=1e15;
int main() {
scanf("%d%d",&n,&m);
for(int i=1; i<=n; ++i) scanf("%lf",a+i);
for(int i=1; i<=n; ++i) scanf("%lf",b+i);
for(int i=1; i<=n; ++i) c[i]=c[n+i]=a[n-i+1];
for(int i=1; i<=n+n; ++i) A[i].x=c[i], B[i].x=b[i];
for(lmt=1,l=0; lmt<(n<<1); lmt<<=1,l++);
for(int i=0; i<lmt; ++i) r[i]=r[i>>1]>>1|((i&1)<<(l-1));
fastFourierTrans(A,1);
fastFourierTrans(B,1);
for(int i=0; i<lmt; ++i) A[i]=A[i]*B[i];
fastFourierTrans(A,-1);
for(int i=0; i<lmt; ++i) A[i].x=floor(A[i].x/lmt+0.5);
for(int i=1; i<=n; ++i) {
sqs+=a[i]*a[i]+b[i]*b[i];
sco+=2*(a[i]-b[i]);
dif=max(dif,A[n+i].x);
}
for(int i=-m; i<=m; ++i) {
ans=min(ans,sqs+n*i*i+sco*i-2*dif);
}
printf("%.0f
",ans);
return 0;
}
忘掉(LaTeX)吧。。