我的室友最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她。每个手环上各有n个装饰物,并且每个装饰物都有一定的亮度。但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有 装饰物的亮度增加一个相同的自然数c(即非负整数)。并且由于这个手环是一个圆,可以以任意的角度旋转它, 但是由于上面装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号 1,2,…,n, 其中 n为每个手环的装饰物个数,第 1 个手环的 i 号位置装饰物亮度为 xi,第 2 个手环的 i 号位置装饰物亮度为yi,两个手环之间的差异值为(参见输入输出样例和样例解释): \sum_{i=1}^{n}(x_i-y_i)^2麻烦你帮他计算一下,进行调整(亮度改造和旋转),使得两个手环之间的差异值最小, 这个最小值是多少呢?
这道题我们可以先化一下式子,sigma(((xi+c)-yi)^2)(c可正可负,因为如果为负,其实就相当于给yi+c),化成了sigma(xi^2-2* xi* yi+yi*yi+c*c+2*c*xi-2*c*yi)。其中的2* xi* yi是以不同开头来开始的,其实我们可以很快发现这东西可以用fft来求,而然后剩下的c*c+2*c*xi-2*c*yi,我们可以运用初中的数学知识O(1)快速求出最小值,但由于c要取整,所以-b/2a时要++时再算一次,–时再算一次。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int maxn=50010;
const double pi=acos(-1.0);
struct complex
{
double r,i;
complex(){}
complex(double _r,double _i){r=_r,i=_i;}
friend complex operator +(const complex &x,const complex &y){return complex(x.r+y.r,x.i+y.i);}
friend complex operator -(const complex &x,const complex &y){return complex(x.r-y.r,x.i-y.i);}
friend complex operator *(const complex &x,const complex &y){return complex(x.r*y.r-x.i*y.i,x.r*y.i+x.i*y.r);}
}a1[maxn*4],a2[maxn*4],b1[maxn*4],b2[maxn*4];
int n,m;
int R[maxn*4];
void fft(complex *y,int len,int on)
{
for(int i=0;i<len;i++)if(i<R[i])swap(y[i],y[R[i]]);
for(int i=1;i<len;i*=2)
{
complex wn(cos(pi/i),sin(pi*on/i));
for(int j=0;j<len;j+=i*2)
{
complex w(1,0);
for(int k=0;k<i;k++,w=w*wn)
{
complex u=y[j+k];
complex v=y[j+k+i]*w;
y[j+k]=u+v;
y[j+k+i]=u-v;
}
}
}
if(on==-1)for(int i=0;i<len;i++)y[i].r/=len;
}
int main()
{
double wy,ans=0.0,s=0.0;
scanf("%d%lf",&n,&wy);n--;
for(int i=0;i<=n;i++)
{
scanf("%lf",&a1[i].r),a2[n-i].r=a1[i].r;
ans+=a1[i].r*a1[i].r;s+=a1[i].r;
}
for(int i=0;i<=n;i++)
{
scanf("%lf",&b1[i].r),b2[n-i].r=b1[i].r;
ans+=b1[i].r*b1[i].r,s-=b1[i].r;
}
m=n+n;int L=0;
for(n=1;n<=m;n*=2)L++;
for(int i=0;i<=n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
fft(a1,n,1);fft(a2,n,1);fft(b1,n,1);fft(b2,n,1);
for(int i=0;i<=n;i++)a1[i]=a1[i]*b2[i];
for(int i=0;i<=n;i++)a2[i]=a2[i]*b1[i];
fft(a1,n,-1);fft(a2,n,-1);
double ss=0.0;
for(int i=0;i<=m/2-1;i++)ss=max(ss,a1[i].r+a2[m/2-i-1].r);
ans-=2.0*ss;
int he;double hehe=999999999.0;
he=-s/(m/2+1)-1;
hehe=min(hehe,(m/2+1)*he*he+2.0*he*s);
he++;
hehe=min(hehe,(m/2+1)*he*he+2.0*he*s);
he++;
hehe=min(hehe,(m/2+1)*he*he+2.0*he*s);
printf("%.0lf\n",hehe+ans);
return 0;
}