zoukankan      html  css  js  c++  java
  • 礼物:多项式

    Description:

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

    但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!

    他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的整数x(可能是负数)。

    并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。

    在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号1,2,...,n,其中n为每个手环的装饰物个数。第一个手环的i号位置装饰物亮度为$a_i$ ,第二个手环的j号位置装饰物亮度$b_j$。两个手环之间的差异值为:$sumlimits_{i=1}^{n} (a_i-b_i)^2$

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

    n<=50000 m<=100

    skyh说这道题是水题。

    然后NC在那里笑,我就以为是skyh在骗我。于是我想暴打他。

    然而我在化学学考上想了十几分钟就会了,所以我就不打算暴打skyh了。

    断环成链是常识。

    ——By Paris

    所以就把一个手环断开。

    先假如它已经对齐了。想想最后的答案吧。

    $sumlimits_{i=1}^{n} (a_i - b_i - x)^2$

    $=sumlimits_{i=1}^{n} a_i^2 + b_i^2 + x^2 -2a_i x + 2 b_i x - 2 a_i b_i$

    于是发现关于x的部分可以解一元二次方程解决。然而我不会,所以枚举x值取最优也是可以的。

    (我本来会的可是不知道为什么WA90自闭)

    所以上面这个式子唯一一个需要求的就是$sumlimits_{i=1}^{n} a_i imes b_i$

    而这里ab可以错位,错位之后还要求和。怎么办?

    假如对齐位置是p,那么断环成链后就是$sumlimits_{i=1}^{n} a_{p+i} imes b_i$

    这个形式就是《快速傅丽叶变化之二》。把b翻转就完了。

     1 #include<cstdio>
     2 #define mod 998244353
     3 #define int long long
     4 int max(int a,int b){return a>b?a:b;}
     5 int a[263333],b[263333],n,A,B,ans,len=1,rev[263333],mx=-1e16,m,mx2=-1e16;
     6 int pow(int b,int t,int a=1){for(;t;t>>=1,b=b*b%mod)if(t&1)a=a*b%mod;return a;}
     7 void NTT(int *a,int opt){
     8     for(int i=0;i<len;++i)if(rev[i]>i)a[i]^=a[rev[i]]^=a[i]^=a[rev[i]];
     9     for(int mid=1;mid<len;mid<<=1)
    10         for(int i=0,t=pow(3,(mod-1)/mid/2*opt+mod-1);i<len;i+=mid<<1)
    11             for(int j=0,w=1,x,y;j<mid;++j,w=w*t%mod)
    12                 x=a[i+j],y=a[i+j+mid]*w%mod,a[i+j]=(x+y)%mod,a[i+j+mid]=(x-y+mod)%mod;
    13     if(opt==-1)for(int i=0,iv=pow(len,mod-2);i<len;++i)a[i]=a[i]*iv%mod;
    14 }
    15 signed main(){
    16     scanf("%lld%lld",&n,&m);
    17     for(int i=0;i<n;++i)scanf("%lld",&a[i]),ans+=a[i]*a[i],a[i+n]=a[i],A+=a[i];
    18     for(int i=0;i<n;++i)scanf("%lld",&b[i]),ans+=b[i]*b[i],B+=b[i];
    19     while(len<=n*3)len<<=1;
    20     for(int x=-m;x<=m;++x)mx2=max(mx2,-n*x*x+2*(A-B)*x);
    21     ans-=mx2;
    22     for(int i=0;i<n-1-i;++i)b[i]^=b[n-1-i]^=b[i]^=b[n-1-i];
    23     for(int i=1;i<len;++i)rev[i]=rev[i>>1]>>1|(i&1?len>>1:0);
    24     NTT(a,1);NTT(b,1);for(int i=0;i<len;++i)a[i]=a[i]*b[i]%mod;NTT(a,-1);
    25     for(int i=0;i<n;++i)mx=max(mx,a[i+n]);
    26     printf("%lld
    ",ans-2*mx);
    27 }
    我还是想暴打skyh怎么办啊?
  • 相关阅读:
    Web前端学习笔记之BootStrap
    js 闭包解决方案
    函数节流简要解析
    js 观察者模式
    arguments解析
    js 职责链模式简要介绍
    js 工厂模式简要介绍
    jsonp跨域总结
    算法复杂度
    正则表达式的$
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12012631.html
Copyright © 2011-2022 走看看