Luogu

分析

显然两个手环增加非负整数亮度,等于其中一个增加一个整数亮度。

设亮度改变了 $c$,则新的差异值为
$$
\sum\limits_{i=1}^n(a_i-b_i+c)
$$
拆开得到
$$
\sum\limits_{i=1}^na_i^2+\sum\limits_{i=1}^nb_i^2+nc^2+2c\left[\sum\limits_{i=1}^n(a_i-b_i)\right]-2\sum\limits_{i=1}^na_ib_i
$$
前面两项是定值;带 $c$ 的两项是关于 $c$ 的二次函数,而且因为 $n>0$,所以有最小值,可以直接算出来;最后一项可以倍长 $a$ 并翻转,然后和 $b$ 卷积即可求出每个旋转角度的值,取个 $\max$ 即可。

代码

//It is made by M_sea
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define re register
typedef int mainint;
#define int long long
using namespace std;

inline int read() {
    int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
    return X*w;
}

struct Complex {
    double r,i;
    Complex(double r_=0,double i_=0) { this->r=r_,this->i=i_; }
    Complex operator +(const Complex& x) { return Complex(r+x.r,i+x.i); }
    Complex operator -(const Complex& x) { return Complex(r-x.r,i-x.i); }
    Complex operator *(const Complex& x) { return Complex(r*x.r-i*x.i,r*x.i+i*x.r); }
};

const int MAXN=400000+10;
const double PI=acos(-1.0);

int r[MAXN];

inline void FFT(Complex* a,int op,int n) {
    for (re int i=0;i<n;++i)
        if (i<r[i]) swap(a[i],a[r[i]]);
    for (re int i=1;i<n;i<<=1) {
        Complex rot(cos(PI/i),op*sin(PI/i));
        for (re int j=0;j<n;j+=i<<1) {
            Complex w(1,0);
            for (re int k=0;k<i;++k,w=w*rot) {
                Complex x=a[j+k],y=w*a[j+k+i];
                a[j+k]=x+y,a[j+k+i]=x-y;
            }
        }
    }
    if (op==-1)
        for (re int i=0;i<=n;++i) a[i].r/=n;
}

int n,m;
Complex f[MAXN],g[MAXN];
int a[MAXN],b[MAXN];

mainint main() {
    n=read(),m=read();
    int ans=0,delta=0;
    for (re int i=1;i<=n;++i) a[i]=read(),ans+=a[i]*a[i],delta+=a[i];
    for (re int i=1;i<=n;++i) b[i]=read(),ans+=b[i]*b[i],delta-=b[i];
    int axis=(int)(round(-(double)delta/n)+0.5); //对称轴
    int tmp=2147483647;
    for (re int i=-1;i<=1;++i) { //check一下左右,不然会WA on #20
        int now=axis+i;
        tmp=min(tmp,n*now*now+2*now*delta);
    }
    ans+=tmp;

    for (re int i=1;i<=n;++i) f[i].r=f[i+n].r=a[i];
    for (re int i=1;i<=n;++i) g[i].r=b[n-i+1];
    int len=1,l=0;
    for (;len<=n*3;len<<=1,++l);
    for (re int i=0;i<len;++i) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    FFT(f,1,len); FFT(g,1,len);
    for (re int i=0;i<=len;++i) f[i]=f[i]*g[i];
    FFT(f,-1,len);

    int mx=-2147483647;
    for (re int i=1;i<=n;++i) mx=max(mx,(int)(f[i+n].r+0.5));
    printf("%lld\n",ans-2*mx);
    return 0;
}
最后修改:2021 年 03 月 23 日 10 : 42 AM