题目大意
给出两个长度都为
n
的数环,环上第
数据范围
解题报告
ans=min∑i=0n−1(xi−yi+c)2=min(∑i=0n−1(x2i+y2i−2xiyi)+(nc2+2c∑i=0n−1(xi−yi)))
对于第一部分我们只需要考虑求
max∑i=0n−1xiyi
;
第二部分可以根据二次函数的性质或者直接在
−m
到
m
枚举
用
x0i
和
y0i
表示一开始的数环,则旋转
k
个位置时,
看起来像是卷积的形式,但是还需要一点小小的变化。
将
y0
反转一下,记为
y1
,则
yi=y1n−i−1
,
∑i=0n−1xiyi=∑i=0n−1x0iy1n−i−1+k
.
则做一次卷积就可以求出
k∈[0,n−1]
的所有情况,取个最大值就行了。
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define max_N 150005
struct cp{
double r,i;
cp(double r=0,double i=0):r(r),i(i){}
cp operator+(const cp&o){
return cp(r+o.r,i+o.i);
}
cp operator-(const cp&o){
return cp(r-o.r,i-o.i);
}
cp operator*(const cp&o){
return cp(r*o.r-i*o.i,r*o.i+i*o.r);
}
};
int rev[max_N];
int gint(){
char c; int f=1;
while(c=getchar(),c<48||c>57)
if(c=='-')f=-1;
int x=0;
for(;c>47&&c<58;c=getchar()){
x=x*10+c-48;
}
return x*f;
}
const double pi=acos(-1.);
cp w[2][max_N];
void fft_init(int n){
cp g(cos(pi*2/n),sin(pi*2/n));
w[0][0]=w[1][0]=cp(1,0);
for(int i=1;i<n;++i)w[0][i]=w[0][i-1]*g;
for(int i=1;i<n;++i)w[1][i]=w[0][n-i];
}
void brc(int n,int l){
for(int i=1;i<n;++i){
rev[i]=(rev[i>>1]>>1)^((i&1)<<l-1);
}
}
void fft(cp*a,int n,int t){
for(int i=0;i<n;++i){
if(rev[i]<i)swap(a[i],a[rev[i]]);
}
for(int i=2;i<=n;i<<=1)
for(int j=0;j<n;j+=i)
for(int k=0;k<i>>1;++k){
cp tmp=w[t][n/i*k]*a[j+k+(i>>1)];
a[j+k+(i>>1)]=a[j+k]-tmp;
a[j+k]=a[j+k]+tmp;
}
if(t)for(int i=0;i<n;++i)a[i].r/=n;
}
int n,m,fft_n,fft_l;
cp x[max_N],y[max_N];
typedef long long ll;
ll ans,tmp;
inline ll calc(ll k,ll M){
return k*k*n+2*M*k;
}
int main(){
n=gint(),m=gint();
for(int i=0;i<n;++i){
x[i].r=gint(),tmp+=x[i].r;
}
for(int i=0;i<n;++i){
y[i].r=gint(),tmp-=y[i].r;
}
ans=calc(0,tmp);
for(int i=1;i<=m;++i){
ans=min(ans,calc(i,tmp));
ans=min(ans,calc(-i,tmp));
}
for(int i=0;i<n;++i){
ans+=1ll*x[i].r*x[i].r+1ll*y[i].r*y[i].r;
}
for(int i=0;i*2<n;++i){
swap(y[i],y[n-i-1]);
}
for(int i=n;i<n*2;++i){
y[i]=y[i-n];
}
while((1<<fft_l)<n*2)++fft_l;
fft_n=1<<fft_l;
fft_init(fft_n);
brc(fft_n,fft_l);
fft(x,fft_n,0);
fft(y,fft_n,0);
for(int i=0;i<fft_n;++i){
x[i]=x[i]*y[i];
}
fft(x,fft_n,1);
tmp=0;
for(int k=0;k<n;++k){
tmp=max(tmp,ll(x[n+k-1].r+0.5));
}
ans-=2*tmp;
printf("%lld\n",ans);
return 0;
}