P3723 [AH2017/HNOI2017]礼物

题目

P3723 [AH2017/HNOI2017]礼物

做法

定义\(r\)为增加的亮度,其实我们可以定义\(r=-m\)~\(m\),简化成对一个环处理亮度

则我们要求最小值:

\[\begin{aligned} &\sum\limits_{i=1}^n(x_i+y_i+r)^2\\ &=\sum\limits_{i=1}^n(x_i^2+y_i^2-2x_iy_i-2y_ir+2x_ir+r^2)\\ &=(\sum\limits_{i=1}^nx_i^2+\sum\limits_{i=1}^ny_i^2)+(nr^2+2r(\sum\limits_{i=1}^na_i-\sum\limits_{i=1}^nb_i))-2\sum\limits_{i=1}^nx_iy_i \end{aligned}\]

其中左部分\(O(n)\),中间枚举\(O(m)\)

右部分\(\sum\limits_{i=1}^nx_iy_i\)\(x\)数组翻转一下,就成了卷积形式,然后再复制一倍,FFT后,\(A_{n+1}\)~\(A_{2n}\)就是不同的对接环形式,然后暴力枚举\(r\)

时间复杂度\(O(3nlog(3n)+nm)\)

My complete code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<ctime>
#include<cmath>
#include<vector>
using namespace std;
typedef int LL;
inline 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<<3)+(x<<1)+c-'0',c=getchar();
	return x*f;
}
const LL maxn=1e6,inf=0x3f3f3f3f;
const double Pi=acos(-1.0);
struct complex{
	double x,y;
	complex (double xx=0,double yy=0){x=xx,y=yy;}
}A[maxn],B[maxn];
LL n,m,a1,b1,a2,b2,limit,L,N,ans;
LL a[maxn],b[maxn],c[maxn],R[maxn];
complex operator -(complex x,complex y){
	return complex(x.x-y.x,x.y-y.y);
}
complex operator +(complex x,complex y){
	return complex(x.x+y.x,x.y+y.y);
}
complex operator *(complex x,complex y){
	return complex(x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x);
}
inline void FFT(complex *A,LL type){
	for(LL i=0;i<limit;++i)
	    if(i<R[i])
	        swap(A[i],A[R[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);
            for(int k=0;k<mid;++k,w=w*WN){
                complex x=A[j+k],y=w*A[j+mid+k];
                A[j+k]=x+y,
                A[j+mid+k]=x-y;
            }
        }
    }
}
int main(){
	n=Read(),m=Read();
	for(LL i=1;i<=n;++i)
		a[i]=Read(),a1+=a[i]*a[i],a2+=a[i];
	for(LL i=1;i<=n;++i)
		b[i]=Read(),b1+=b[i]*b[i],b2+=b[i];
	for(LL i=1;i<=n;++i)
		c[i]=a[n-i+1],c[n+i]=c[i];
	N=3*n;
	limit=1,L=0;
	while(limit<N)
	    limit<<=1,++L;
	for(LL i=0;i<limit;++i)
	    A[i]=complex(1.0*c[i],0.0);
	for(LL i=0;i<limit;++i)
	    B[i]=complex(1.0*b[i],0.0);
	for(LL i=0;i<limit;++i)
	    R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
	FFT(A,1),FFT(B,1);
	for(LL i=0;i<limit;++i)
	    A[i]=A[i]*B[i];
	FFT(A,-1); ans=inf;
	for(LL i=1;i<=n;++i)
		for(LL j=-m;j<=m;++j)
			ans=min(ans,a1+b1+(j*j*n+2*j*(a2-b2))-2*(LL)(A[i+n].x/limit+0.5));
	printf("%d\n",ans);
	return 0;
}
posted @ 2019-01-19 22:59  y2823774827y  阅读(138)  评论(0编辑  收藏  举报