zoukankan      html  css  js  c++  java
  • [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+2asum_{i=1}^{n}(x_i-y_i)-2sum_{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
    ",ans);
    }
    
    


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

  • 相关阅读:
    laravel 创建自定义全局函数
    JAVA堆栈的区别
    项目经验-国家电网
    OO开发思想:面向对象的开发方法(Object oriented,OO)
    分层开发思想
    软件开发过程与思想
    json学习笔记
    UNIX网络编程——UDP 中的外出接口的确定
    UNIX网络编程——UDP缺乏流量控制(改进版)
    UNIX网络编程——UDP 的connect函数(改进版)
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/10248824.html
Copyright © 2011-2022 走看看