[AH2017/HNOI2017]礼物【FFT】

[AH2017/HNOI2017]礼物
题目大意:有两个只能旋转不能翻转的环,环上每个点有一定的权值,可以把其中一个环的权值全增加(c),最小化改变(旋转和增加权值)后的(sum_{i=0}^{n-1}(x_i-y_i)^2)
(1 le nle 5*{10}^4, 1le mle 100, 1le a_ile m)(m为初始权值的最大值)
(f[k][i])为第一个环的(0)号点对齐第二个环的(i)号节点,使第一个环权值增加(k)(sum_{i=0}^{n-1}(x_i-y_i)^2)的值
(Sx=sum_{i=0}^{n-1}x_i, Sy=sum_{i=0}^{n-1}y_i, Sx2=sum_{i=0}^{n-1}x_i^2, Sy2=sum_{i=0}^{n-1}y_i^2)
则$$egin{aligned}
f[k][i]&=sum_{j=0}{n-1}(x_j-y_{j+i}+k)2
&=sum_{j=0}{n-1}(x_j2+2x_j(k-y_{j+i})+(k-y_{j+i})^2)
&=Sx2+Sy2+2k(Sx-Sy)+nk2-2sum_{j=0}{n-1}x_jy_{j+i}
end{aligned}

[令$b_i=x_{n-1-i}$,即$x_i=b_{n-1-i}$ 则$f[k][i]=-2(b*y)(n-1+i)+Sx2+Sy2+2k(Sx-Sy)+nk^2$ 令$g(n)=(b*y)(n)$预处理出$g$ 把看$k$看做变量,这就是一个二次函数 显然,$n > 0$,对称轴为$-frac{Sx-Sy}{n}, f[i]$在对称轴处取最小值, 分别求$f[i]$在$k=-lfloorfrac{Sx-Sy}{n} floor$与$k=-lceilfrac{Sx-Sy}{n} ceil$的取值取最小 对称轴是固定的,只要求出$-2g_{2n-2+i}$的最小值就好 那么就结束啦($FFT$的板我就不贴了) ```cpp void solve(){ n=read(), m=read(); for(int i=1, x; i <= n; i++) x=read(), sx+=x, sx2+=x*x, f[n-i].a=x; for(int i=0, y; i < n; i++) y=read(), sy+=y, sy2+=y*y, g[i].a=y, g[n+i].a=y; while(lim < n*3) lim<<=1, l++; for(int i=0; i < lim; i++) r[i]=r[i>>1]>>1|((i&1)<<l-1); FFT(f, 1); FFT(g, 1); for(int i=0; i < lim; i++) f[i]=f[i]*g[i]; FFT(f, -1); for(int i=n-1; i < n*2-1; i++) G=max((int)floor(f[i].a/lim+0.5), G); int k1=floor(1.0*(sy-sx)/n), k2=ceil(1.0*(sy-sx)/n); int ans=-2*G+min(n*k1*k1+2*k1*(sx-sy), n*k2*k2+2*k2*(sx-sy))+sx2+sy2; printf("%d", ans); } ```]

原文地址:https://www.cnblogs.com/zerolt/p/9308975.html