https://www.lydsy.com/JudgeOnline/problem.php?id=4827
式子化简一下,发现最后只跟 Σ xi*yi 有关
第二个序列反转,就可以用FFT优化
注意:
循环会想到将序列复制一遍,但只能复制一个序列,
若n=4,第一个序列为1 2 3 4,,第二个序列为5 6 7 8
只复制第一个序列,1 2 3 4 1 2 3 4
当i=5时,f[i]=2*0+1*0+4*8+3*7+2*6+1*5
如果第二个序列也复制,那么上面*0的地方将会出错
#include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int N=(1<<18)+2; const double pi=acos(-1); int a[N],b[N]; struct Complex { double x,y; Complex(double x_=0,double y_=0):x(x_),y(y_){} Complex operator + (Complex P) { return Complex(x+P.x,y+P.y); } Complex operator - (Complex P) { return Complex(x-P.x,y-P.y); } Complex operator * (Complex P) { return Complex(x*P.x-y*P.y,x*P.y+y*P.x); } }; typedef Complex E; E A[N],B[N]; int rev[N]; int f[N]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-‘0‘; c=getchar(); } } void fft(E *a,int len,int ty) { for(int i=0;i<len;++i) if(i<rev[i]) swap(a[i],a[rev[i]]); for(int i=1;i<len;i<<=1) { E wn(cos(pi/i),ty*sin(pi/i)); for(int p=i<<1,j=0;j<len;j+=p) { E w(1,0); for(int k=0;k<i;++k,w=w*wn) { E x=a[j+k],y=a[j+k+i]*w; a[j+k]=x+y; a[j+k+i]=x-y; } } } if(ty==-1) { for(int i=0;i<len;++i) a[i].x=a[i].x/len+0.5; } } int main() { int n,m; read(n); read(m); long long sum2=0,sum=0; for(int i=1;i<=n;++i) { read(a[i]); sum+=a[i]; sum2+=a[i]*a[i]; } for(int i=1;i<=n;++i) { read(b[i]); sum-=b[i]; sum2+=b[i]*b[i]; } for(int i=0;i<n;++i) A[i].x=a[i+1]; for(int i=0;i<n;++i) A[n+i].x=a[i+1]; for(int i=n,j=0;i;--i,++j) B[j].x=b[i]; int num=3*n-3,len=1,bit=0; while(len<num) len<<=1,bit++; for(int i=0;i<len;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<bit-1); fft(A,len,1); fft(B,len,1); for(int i=0;i<len;++i) A[i]=A[i]*B[i]; fft(A,len,-1); long long ab=0; /* ab=A[n-1].x; for(int i=0;i<n-1;++i) ab=max(ab,(long long)A[i+n].x+(long long)A[i].x); */ for(int i=0;i<n;++i) ab=max(ab,(long long)A[i+n-1].x); ab<<=1; long long mi=2e18; for(int c=-m;c<=m;++c) mi=min(mi,1LL*n*c*c+1LL*2*c*sum); cout<<sum2-ab+mi; }