• [HNOI2017] 礼物


    可以发现,(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)吧。。

  • 相关阅读:
    世界上最遥远的距离(泰戈尔)
    肩周炎?
    [转]C#基础概念二十五问
    [转]ASP.NET 2.0的缓存技术简介
    SQL Server 2005下的分页SQL
    [转]基本的缓存类操作封装(抽象类)
    GridView鼠标经过行变色
    推荐一个好用的.NET2.0下的发送EMail的库
    Data Access Application Block for .NET
    Pet Shop 4.0的缓存机制
  • 原文地址:https://www.cnblogs.com/nosta/p/10184949.html
Copyright © 2020-2023  润新知