洛谷P3723 [AH2017/HNOI2017]礼物

吴迪说他化学会考上十分钟就想出来了,太神了%%%不过我也十分钟

但是调了一个多小时啊大草

懒得人话翻译了,自己康吧:

我的室友(真的是室友吗?)最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她。每个手环上各有 \(n\) 个装饰物,并且每个装饰物都有一定的亮度。

但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的非负整数 \(c\)。并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。

在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号 \(1 \sim n\),其中 \(n\) 为每个手环的装饰物个数, 第 \(1\) 个手环的 \(i\) 号位置装饰物亮度为 \(x_i\)​,第 \(2\) 个手环的 \(i\) 号位置装饰物亮度为 \(y_i\)​,两个手环之间的差异值为(参见输入输出样例和样例解释):
\[\sum\limits_{i=1}^{n}(x_i-y_i)^2\]

麻烦你帮他计算一下,进行调整(亮度改造和旋转),使得两个手环之间的差异值最小,这个最小值是多少呢?

对于 \(100\%\) 的数据,\(1 \le n \le 50000, 1 \le a_i \le m \le 100。\)

考虑加上一个\(c\)之后式子变为

\[\sum\limits_{i=1}^{n}(x_i-y_i+c)^2\]

拆一下

\[=\sum\limits_{i=1}^{n}x_i^2+y_i^2-2x_iy_i+c^2+c(x_i-y_i)\]

发现求个\(\sum\limits_{i=1}^{n}x_iy_i\)就完了

\(x^{'}\)\(x\)翻转后的序列,那么我们只要求\(\sum\limits_{x=1}^{n}x_{n-i+1}^{'}y_i\)

发现是个卷积,但是对齐的位置可能不一样怎么办呢?

可以倍长一下\(x_i\)再翻转,然后在\(ntt\)之后的系数数组的\(x_{n+1}\sim x_{n+n}\)中选一个

就切了

多项式题目的边界真tm恶心

吴迪的代码为什么那么短啊

#include
using namespace std;
namespace red{
#define int long long
#define lowbit(x) ((x)&(-x))
    inline int read()
    {
        int x=0;char ch,f=1;
        for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        if(ch=='-') f=0,ch=getchar();
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    const int N=5e5+10,p=998244353,g=3,gi=332748118;
    int n,m,limit,len;
    int suma,sumb,sum;
    int ret=1e9+7;
    int a[N],pos[N];
    int b[N];
    inline int fast(int x,int k)
    {
        int ret=1;
        while(k)
        {
            if(k&1) ret=ret*x%p;
            x=x*x%p;
            k>>=1;
        }
        return ret;
    }
    inline void ntt(int *a,int inv)
    {
        for(int i=0;i=p) a[j+k]-=p;
                    a[j+k+mid]=x-y;
                    if(a[j+k+mid]<0) a[j+k+mid]+=p;
                }
            }
        }
    }
    inline void main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;++i) a[i]=a[i+n]=read(),suma+=a[i],sum+=a[i]*a[i];
        for(int i=1;i<=n;++i) b[i]=read(),sumb+=b[i],sum+=b[i]*b[i];
        reverse(a+1,a+2*n+1);
        for(limit=1;limit<=3*n;limit<<=1) ++len;
        for(int i=0;i>1]>>1)|((i&1)<<(len-1));
        ntt(a,1),ntt(b,1);
        for(int i=0;i

你可能感兴趣的:(洛谷P3723 [AH2017/HNOI2017]礼物)