洛谷P3723 [AH2017/HNOI2017]礼物

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

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

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

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

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

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

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

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

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

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

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

拆一下

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

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

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

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

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

就切了

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

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

#include<bits/stdc++.h>
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<limit;++i)
			if(i<pos[i]) swap(a[i],a[pos[i]]);
		for(int mid=1;mid<limit;mid<<=1)
		{
			int Wn=fast(inv?g:gi,(p-1)/(mid<<1));
			for(int r=mid<<1,j=0;j<limit;j+=r)
			{
				int w=1;
				for(int k=0;k<mid;++k,w=w*Wn%p)
				{
					int x=a[j+k],y=w*a[j+k+mid]%p;
					a[j+k]=x+y;
					if(a[j+k]>=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<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1));
		ntt(a,1),ntt(b,1);
		for(int i=0;i<limit;++i) a[i]=a[i]*b[i]%p;
		ntt(a,0);
		int inv=fast(limit,p-2);
		for(int i=0;i<limit;++i) a[i]=a[i]*inv%p;
		for(int tmp,i=1;i<=n;++i)
		{
			for(int d=-m;d<=m;++d)
			{
				tmp=sum-2*a[i+n]+d*d*n+2*d*(suma-sumb);
				ret=min(ret,tmp);
			}
		}
		printf("%lld
",ret);
	}
}
signed main()
{
	red::main();
	return 0;
}
/*
5 6
4 5 1 1 3
6 3 3 4 5

*/
原文地址:https://www.cnblogs.com/knife-rose/p/12050231.html