[bzoj 4827][Hnoi2017]礼物

## [ 传送门 ](https://www.lydsy.com/JudgeOnline/problem.php?id=4827)

Description

我的室友最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一个送给她。每个手环上各有 \(n\) 个装饰物,并且每个装饰物都有一定的亮度。但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的自然数 \(c\)(即非负整数)。并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面 装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号 \(1,2,…,n\),其中 \(n\) 为每个手环的装饰物个数,第 \(1\) 个手环的 $i $号位置装饰物亮度为 \(x_i\),第 $2 $个手 环的 $i $号位置装饰物亮度为 \(y_i\),两个手环之间的差异值为(参见输入输出样例和样例解释): \(\sum_{i=1}^{n}(x_i-y_i)^2\)麻烦你帮他计算一下,进行调整(亮度改造和旋转),使得两个手环之间的差异值最小, 这个最小值是多少呢?

Solution

可以看成是A手环的增加量为\(a\),其中\(a\)可以是负数,显然\(-m \leq a \leq m\)

\[ans=min(\sum_{i=1}^{n} (x_i+a-y_i)^2) \]

\[ans=min(\sum_{i=1}^{n}({x_i}^2+{y_i}^2)+2na+2a\sum_{i=1}^{n}(x_i-y_i)-2\sum_{i=1}^{n}x_iy_i) \]

\(a\)的取值可以直接枚举,只需要算出\(\max(\sum_{i=1}^{n}x_iy_i)\)

\(x\)序列翻转,这样就是求\(\max(\sum_{i=1}^{n}x_{n-i+1}y_i)\)了,考虑把翻转后的序列再倍长,直接用\(FFT\)求卷积

最后在\([n+1,n*2]\)上找最大值即可。


Code 

#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
#define MN 2097152
const double Pi=std::acos(-1.);
struct complex
{
	double x,y;
	complex(double _x=0,double _y=0):x(_x),y(_y){}
	inline complex operator+(const complex& o)const{return complex(x+o.x,y+o.y);}
	inline complex operator-(const complex& o)const{return complex(x-o.x,y-o.y);}
	inline complex operator*(const complex& o)const{return complex(x*o.x-y*o.y,x*o.y+y*o.x);}
	inline void swap(complex& o){complex t=o;o=(*this);*this=t;}
}a[MN],b[MN];
int N,di,pos[MN];
inline void FFT(complex *a,int type)
{
	register int i,j,p,k;
    for(i=0;i<N;++i)if(i<pos[i])a[i].swap(a[pos[i]]);
    for(i=1;i<N;i<<=1)
    {
        complex wn(cos(Pi/i),type*sin(Pi/i));
        for(p=i<<1,j=0;j<N;j+=p) 
        {
            complex w(1,0);
            for(k=0;k<i;++k,w=w*wn)
            {
                complex X=a[j+k],Y=w*a[j+i+k];
                a[j+k]=X+Y;a[j+i+k]=X-Y;
            }
        }
    }
}
ll sum,s,ans=5e9;
ll sqr(ll x){return x*x;}
int main()
{
	register int n,m,i,j;
	n=read();m=read();
	for(i=1;i<=n;++i) a[n-i+1].x=a[n*2-i+1].x=read(),sum+=sqr(a[n-i+1].x),s+=a[n-i+1].x*2;
	for(i=1;i<=n;++i) b[i].x=read(),sum+=sqr(b[i].x),s-=b[i].x*2;
	for(N=1;N<=n*3;N<<=1,di++);
    for(i=0;i<N;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(di-1));
    FFT(a,1);FFT(b,1);
    for(i=0;i<N;++i) a[i]=a[i]*b[i];
    FFT(a,-1);
    for(i=0;i<=n*3;++i) a[i].x=(int)(a[i].x/N+.5);
    for(i=1;i<=n;++i)for(j=-m;j<=m;++j) ans=min(ans,sum+1ll*n*sqr(j)+1ll*j*s-2ll*(int)a[n+i].x);
    return 0*printf("%lld\n",ans);
}



Blog来自PaperCloud,未经允许,请勿转载,TKS!

posted @ 2019-01-10 11:09  PaperCloud  阅读(123)  评论(0编辑  收藏  举报