• BZOJ4827: [Hnoi2017]礼物


    BZOJ4827: [Hnoi2017]礼物


    题目描述

    传送门

    题目分析

    发现题目中的式子貌似是让在求

    [sum_{i=1}^{n}(x_i-y_{i+k}+C)^2 ]

    可以大力展开这个式子。
    然后发现有关于(C)的项都可以(O(1))求,二次项也可以(O(1)),就只剩下一个(-2sum_{i=1}^{n}x_iy_{i+k})不是很好。

    当然可以(n^2)枚举,然后问(gay哥)为啥见着这种式子就可以往FFT上想。

    考虑卷积的一般形式是(f(n)=sum_{i=0}^{n}f(n-i)·g(i)),所以可以把前面的那一项反过来,然后破环成链倍长,之后n+1~n+n项中的最大值就是我们要求的最大值。

    是代码呢

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=4e5+7;
    const double pi=acos(-1);
    const int inf=1e9+7;
    inline int read()
    {
        int x=0,c=1;
        char ch=' ';
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        while(ch=='-')c*=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    struct Complex{
    	double x,y;
    	Complex (double xx=0,double yy=0){x=xx,y=yy;}
    	friend Complex operator +(Complex a,Complex b){
    		return Complex(a.x+b.x,a.y+b.y);
    	}
    	friend Complex operator -(Complex a,Complex b){
    		return Complex(a.x-b.x,a.y-b.y);
    	}
    	friend Complex operator *(Complex a,Complex b){
    		return Complex((a.x*b.x)-(a.y*b.y),(a.x*b.y)+(a.y*b.x));
    	}
    }a[MAXN],b[MAXN];
    int n,m,len,r[MAXN],N,l,s1[MAXN],s2[MAXN],s[MAXN],mx=-inf,ans=inf;
    inline void FFT(Complex *A,int type)
    {
    	for(int i=0;i<N;i++) if(i<r[i]) swap(A[i],A[r[i]]);
    	for(int mid=1;mid<N;mid<<=1){
    		Complex wn(cos(pi/mid),type*sin(pi/mid));
    		for(int R=mid<<1,j=0;j<N;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+k+mid]=x-y;
    			}
    		}
    	}
    }
    inline void init()
    {
    	n=read(),m=read();
    	for(int i=1;i<=n;i++) s1[i]=read();
    	for(int i=1;i<=n;i++) s2[i]=read();
    	N=n-1;len=n+n-1;
    	for(int i=0;i<=N;i++) a[i].x=s1[i+1];
    	for(int i=0;i<n;i++) b[i].x=b[i+n].x=s2[n-i];
    	len+=N;
    }
    int main()
    {
    	init();
    	N=1;
    	while(N<=len) N<<=1,l++;
    	for(int i=0;i<N;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    	FFT(a,1);FFT(b,1);
    	for(int i=0;i<N;i++) a[i]=a[i]*b[i];
    	FFT(a,-1);
    	for(int i=0;i<=len;i++) s[i]=(int)(a[i].x/N+0.5);
    	int p1=0,p2=0,t1=0,t2=0;
    	for(int i=1;i<=n;i++) p1+=s1[i]*s1[i],p2+=s2[i]*s2[i],t1+=s1[i],t2+=s2[i];
    	for(int i=1;i<n+n;i++) mx=max(mx,s[i]);
    	for(int C=-m;C<=m;C++){
    		int sum=p1+p2+n*C*C+2*C*t1-2*C*t2-2*mx;
    		ans=min(sum,ans);
    	}
    	printf("%d",ans);
    }
    
  • 相关阅读:
    3-2 案例准备工作
    3-1 Git下载与安装
    3-1 案例环境初始化
    1-2+并发编程初体验
    Linux
    HTTP
    Linux
    HTML
    Linux 命令
    MySQL
  • 原文地址:https://www.cnblogs.com/victorique/p/10435267.html
Copyright © 2020-2023  润新知