【洛谷P3723】礼物

题目

题目链接:https://www.luogu.com.cn/problem/P3723
我的室友最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她。每个手环上各有 \(n\) 个装饰物,并且每个装饰物都有一定的亮度。

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

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

\[\sum_{i=1}^{n} (x_i-y_i)^2 \]

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

思路

假设 \(a\) 旋转之后的序列为 \(c\),那么我们要求的就是

\[\min(\sum^{n}_{i=1}(c_i-b_i+x)) \]

拆开

\[\sum^{n}_{i=1}(c_i^2+b_i^2)+nx^2+2x(c_i-b_i)-2\sum^{n}_{i=1}c_ib_i \]

由于 \(m\leq 100\),所以我们可以 \(O(nm)\) 枚举出除最后一项外的最小值。所以我们只需要让 \(-2\sum^{n}_{i=1}c_ib_i\) 最小即可。
\(c'(i)=c(n-i+1)\),那么原式就变成了一个卷积的形式。拆环为链后直接上 FFT 即可。
时间复杂度 \(O(n\log n+nm)\)

代码

#include <bits/stdc++.h>
#define cp complex<double>
using namespace std;
typedef long long ll;

const int N=500010;
const double pi=acos(-1);
int n,m,lim,rev[N];
ll fsum,gsum,fpow,gpow,ans;
cp f[N],g[N];

void fft(cp *f,int inv)
{
	for (int i=0;i<lim;i++)
		if (rev[i]<i) swap(f[i],f[rev[i]]);
	for (int mid=1;mid<lim;mid<<=1)
	{
		cp temp(cos(pi/mid),inv*sin(pi/mid));
		for (int i=0;i<lim;i+=(mid<<1))
		{
			cp w=cp(1,0);
			for (int j=0;j<mid;j++,w*=temp)
			{
				cp x=f[i+j],y=w*f[i+j+mid];
				f[i+j]=x+y; f[i+j+mid]=x-y;
			}
		}
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=0,x;i<n;i++)
	{
		scanf("%d",&x);
		fpow+=x*x; fsum+=x;
		f[n-i-1]=cp(1.0*x,0.0);
	}
	for (int i=0,x;i<n;i++)
	{
		scanf("%d",&x);
		gpow+=x*x; gsum+=x;
		g[i]=g[i+n]=cp(1.0*x,0.0);
	}
	lim=1; ans=1145140000000000000LL;
	while (lim<=n*3) lim<<=1;
	for (int i=0;i<lim;i++)
		rev[i]=(rev[i>>1]>>1)|((i&1)?(lim>>1):0);
	fft(f,1); fft(g,1);
	for (int i=0;i<lim;i++)
		f[i]*=g[i];
	fft(f,-1);
	for (ll j=-m;j<=m;j++)
		for (int i=n;i<n*2;i++)
			ans=min(ans,fpow+gpow+j*j*n+2LL*j*(fsum-gsum)-2LL*(ll)(f[i].real()/lim+0.4999));
	printf("%lld",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/stoorz/p/13681149.html