首页 > 其他 > 详细

[bzoj 4827][Hnoi2017]礼物

时间:2019-01-10 11:12:27      阅读:137      评论:0      收藏:0      [点我收藏+]

传送门

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!

[bzoj 4827][Hnoi2017]礼物

原文:https://www.cnblogs.com/PaperCloud/p/10248824.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!