题目:BZOJ4827.
题目大意:给定两个环 x , y x,y x,y,其中环 x x x可以全体权值加 c c c(一个自然数),环 y y y可以旋转角度.现在要求操作后 ∑ i = 0 n − 1 ( x i − y i ) 2 \sum_{i=0}^{n-1}(x_i-y_i)^2 ∑i=0n−1(xi−yi)2最小.
1 ≤ n ≤ 5 ∗ 1 0 4 , 1 ≤ m ≤ 100 , 1 ≤ x i , y i ≤ m 1\leq n\leq 5*10^4,1\leq m\leq100,1\leq x_i,y_i\leq m 1≤n≤5∗104,1≤m≤100,1≤xi,yi≤m.
我们把环 x x x要加上 c c c直接写出来:
∑ i = 0 n − 1 ( x i + c − y i ) 2 \sum_{i=0}^{n-1}(x_i+c-y_i)^2 i=0∑n−1(xi+c−yi)2
大力展开:
∑ i = 0 n − 1 ( x i + c − y i ) 2 = ∑ i = 0 n − 1 ( x i 2 + y i 2 + c 2 − 2 x i y i + 2 x i c − 2 y i c ) = n c 2 + ∑ i = 0 n − 1 x i 2 + ∑ i = 0 n − 1 y i 2 + 2 c ∑ i = 0 n − 1 x i − 2 c ∑ i = 0 n − 1 y i − 2 ∑ i = 0 n − 1 x i y i \sum_{i=0}^{n-1}(x_i+c-y_i)^2\\ =\sum_{i=0}^{n-1}(x_i^2+y_i^2+c^2-2x_iy_i+2x_ic-2y_ic)\\ =nc^2+\sum_{i=0}^{n-1}x_i^2+\sum_{i=0}^{n-1}y_i^2+2c\sum_{i=0}^{n-1}x_i-2c\sum_{i=0}^{n-1}y_i-2\sum_{i=0}^{n-1}x_iy_i i=0∑n−1(xi+c−yi)2=i=0∑n−1(xi2+yi2+c2−2xiyi+2xic−2yic)=nc2+i=0∑n−1xi2+i=0∑n−1yi2+2ci=0∑n−1xi−2ci=0∑n−1yi−2i=0∑n−1xiyi
想到能够改变整个式子值的只有 c c c和 x i x_i xi与 y i y_i yi相乘形式的项.
把与 c c c有关的项写出来:
n c 2 + 2 c ( ∑ i = 0 n − 1 x i − ∑ i = 0 n − 1 y i ) nc^2+2c(\sum_{i=0}^{n-1}x_i-\sum_{i=0}^{n-1}y_i) nc2+2c(i=0∑n−1xi−i=0∑n−1yi)
发现这个式子中除了 c c c都是常量,所以考虑把这个式子最小化.发现这玩意是个二次函数,求个对称轴上下取整的值取个最小值即可.
在考虑与 x i y i x_iy_i xiyi有关的项:
− 2 ∑ i = 0 n − 1 x i y i -2\sum_{i=0}^{n-1}x_iy_i −2i=0∑n−1xiyi
把 − 2 -2 −2去掉,就变成了让以下式子最大化:
∑ i = 0 n − 1 x i y i \sum_{i=0}^{n-1}x_iy_i i=0∑n−1xiyi
发现这个式子很像FFT的形式,把 y y y数组翻转一下:
∑ i = 0 n − 1 x i y n − i + 1 \sum_{i=0}^{n-1}x_iy_{n-i+1} i=0∑n−1xiyn−i+1
发现这是个卷积可以用FFT优化计算.
可是我们要的是可以旋转的最大值啊,所以考虑破环成链,倍长 y y y,得到 n n n到 2 n − 1 2n-1 2n−1项之中的最大值既可以作为原来 ∑ i = 0 n − 1 x i y i \sum_{i=0}^{n-1}x_iy_i ∑i=0n−1xiyi的最大值.
总时间复杂度 O ( n log n ) O(n\log n) O(nlogn).
代码如下:
#include
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=262144,C=20;
const double pi=acos(-1);
struct comp{
double a,b;
comp(double A=0,double B=0){a=A;b=B;}
comp operator + (const comp &p){return comp(a+p.a,b+p.b);}
comp operator - (const comp &p){return comp(a-p.a,b-p.b);}
comp operator * (const comp &p){return comp(a*p.a-b*p.b,a*p.b+b*p.a);}
};
int n,m,x[N+9],y[N+9],sum;
int Get_sqrfun(int a,int b,int x){return a*x*x+b*x;}
int len,rev[N+9];
comp pw[N+9],a[N+9],b[N+9];
void Get_len(int n){
int l=0;
for (len=1;len<=n;len<<=1) ++l;
for (int i=0;i<len;++i) rev[i]=rev[i>>1]>>1|(i&1)<<l-1;
}
void FFT(comp *a,int n,int t){
for (int i=0;i<n;++i)
if (i<rev[i]) swap(a[i],a[rev[i]]);
for (int i=1;1<<i<=n;++i){
int len=1<<i;
comp wn=comp(cos(2.0*pi/len),sin(2.0*pi/len)*(t?-1:1));
pw[0]=comp(1,0);
for (int j=1;j<len>>1;++j) pw[j]=pw[j-1]*wn;
for (int j=0;j<n;j+=len)
for (int k=0;k<len>>1;++k){
comp x=a[j+k],y=pw[k]*a[j+k+(len>>1)];
a[j+k]=x+y;a[j+k+(len>>1)]=x-y;
}
}
}
void Poly_mul(comp *a,comp *b,int n,int m){
Get_len(n+m);
FFT(a,len,0);
FFT(b,len,0);
for (int i=0;i<len;++i) a[i]=a[i]*b[i];
FFT(a,len,1);
for (int i=0;i<len;++i) a[i].a=a[i].a/len+0.5;
}
int ans;
Abigail into(){
scanf("%d%d",&n,&m);
for (int i=0;i<n;++i){
scanf("%d",&x[i]);
ans+=x[i]*x[i];
sum+=x[i];
}
for (int i=0;i<n;++i){
scanf("%d",&y[i]);
ans+=y[i]*y[i];
sum-=y[i];
}
}
Abigail work(){
ans+=min(Get_sqrfun(n,sum<<1,floor(-1.0*sum/n)),Get_sqrfun(n,sum<<1,ceil(-1.0*sum/n)));
for (int i=0;i<n;++i) a[i]=x[i],b[i]=b[i+n]=y[n-i-1];
Poly_mul(a,b,n-1,n*2-1);
int t=0;
for (int i=n;i<n<<1;++i) t=max(t,(int)a[i].a);
ans-=t<<1;
}
Abigail outo(){
printf("%d\n",ans);
}
int main(){
into();
work();
outo();
return 0;
}