礼物:多项式

Description:

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

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

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

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

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

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

n<=50000 m<=100

skyh说这道题是水题。

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

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

断环成链是常识。

——By Paris

所以就把一个手环断开。

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

$\sum\limits_{i=1}^{n} (a_i - b_i - x)^2$

$=\sum\limits_{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自闭)

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

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

假如对齐位置是p,那么断环成链后就是$\sum\limits_{i=1}^{n} a_{p+i} \times 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\n",ans-2*mx);
27 }
我还是想暴打skyh怎么办啊?
posted @ 2019-12-09 18:07  DeepinC  阅读(242)  评论(2编辑  收藏  举报