BZOJ:4827: [Hnoi2017]礼物
【问题描述】
我的室友最近喜欢上了一个可爱的小女生。马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一个送给她。每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度。
但是在她生日的前一天,我的室友突然发现他好像拿错了一个手环,而且已经没时间去更换它了!他只能使用一种特殊的方法,将其中一个手环中所有装饰物的亮度增加一个相同的自然数 c(即非负整数)。并且由于这个手环是一个圆,可以以任意的角度旋转它,但是由于上面 装饰物的方向是固定的,所以手环不能翻转。需要在经过亮度改造和旋转之后,使得两个手环的差异值最小。
在将两个手环旋转且装饰物对齐了之后,从对齐的某个位置开始逆时针方向对装饰物编号 1,2,…,n,其中 n 为每个手环的装饰物个数,第 1 个手环的 i 号位置装饰物亮度为 xi,第 2 个手 环的 i 号位置装饰物亮度为 yi,两个手环之间的差异值为(参见输入输出样例和样例解释): ∑(𝑥𝑖 − 𝑦𝑖 ) 2 𝑛 𝑖=1 麻烦你帮他计算一下,进行调整(亮度改造和旋转),使得两个手环之间的差异值最小, 这个最小值是多少呢?
【输入格式】
输入数据的第一行有两个数n, m,代表每条手环的装饰物的数量为n,每个装饰物的初始 亮度小于等于m。
接下来两行,每行各有n个数,分别代表第一条手环和第二条手环上从某个位置开始逆时 针方向上各装饰物的亮度。
【输出格式】
输出一个数,表示两个手环能产生的最小差异值。
注意在将手环改造之后,装饰物的亮度 可以大于 m。
【输入样例】
5 6
1 2 3 4 5
6 3 3 4 5
【输入样例】
1
【样例解释】
需要将第一个手环的亮度增加1,第一个手环的亮度变为: 2 3 4 5 6 旋转一下第二个手环。对于该样例,是将第二个手环的亮度6 3 3 4 5向左循环移动 2017-04-15 第 6 页,共 6 页 一个位置,使得第二手环的最终的亮度为:3 3 4 5 6。 此时两个手环的亮度差异值为1。
【数据范围】
30%的数据满足n≤500, m≤10; 70%的数据满足n≤5000; 100%的数据满足1≤n≤50000, 1≤m≤100, 1≤ai≤m。
写了这么久NTT,现在连FFT都不会写了,是不是药丸啊。
稍微推导可以得到:$d=-\frac{S_x-S_y}{n}$(四舍五入一下)
再做一下循环卷积求出$\sum X_iY_i$的最大值就吼了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cmath> #include<cstdio> #include<algorithm> #define MN 500001 #define ld double using namespace std; int read_p,read_ca; inline int read(){ read_p=0;read_ca=getchar(); while(read_ca<'0'||read_ca>'9') read_ca=getchar(); while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p; } const ld pi=4.*atan(1.); struct na{ld r,i;na(ld _r=0,ld _i=0):r(_r),i(_i){};}A[MN],B[MN],C[MN]; na operator * (na a,na b){return na(a.r*b.r-a.i*b.i,a.r*b.i+b.r*a.i);} na operator + (na a,na b){return na(a.r+b.r,a.i+b.i);} na operator - (na a,na b){return na(a.r-b.r,a.i-b.i);} int n,m,x[MN],y[MN],MMH=0,sx=0,sy=0,d,ma=0,tot; inline int max(int a,int b){return a>b?a:b;} void FFT(int N,na a[],int f){ for (int i=0,j=0;i<N;i++){ if (i>j) swap(a[i],a[j]); for (int k=N>>1;(j^=k)<k;k>>=1); } for (int i=2;i<=N;i<<=1) for (int m=i>>1,j=0;j<N;j+=i){ na wn=na(cos(2.*pi/i),sin(2.*pi/i)*f),w=na(1,0); for (int k=0;k<m;k++){ na Z=a[j+k+m]*w; a[j+k+m]=a[j+k]-Z; a[j+k]=a[j+k]+Z; w=w*wn; } } } int main(){ register int i; n=read();m=read(); for (tot=1;tot<(n<<1);tot<<=1); for (i=0;i<n;i++) x[i]=read(),sx+=x[i]; for (i=0;i<n;i++) y[i]=read(),sy+=y[i]; d=int(round(-1.*(sx-sy)/n)); for (i=0;i<n;i++) MMH+=(x[i]+d)*(x[i]+d)+y[i]*y[i]; for (i=0;i<n;i++) A[i]=na(x[n-i-1]+d),B[i]=na(y[i]); FFT(tot,A,1);FFT(tot,B,1); for (i=0;i<tot;i++) C[i]=A[i]*B[i]; FFT(tot,C,-1); for (i=0;i<n;i++) ma=max(ma,int((C[i].r+C[n+i].r)/tot+0.5)); printf("%d\n",MMH-ma-ma); }