[AH2017/HNOI2017]礼物
题解:
水题
化简一波式子会发现就是个二次函数再加上一个常数
而只有常数中的-2sigma(xiyi)是随移动而变化的
所以只要o(1)求出二次函数最大值然后搞出sigma(xiyi)就可以了
这个东西显然只要将一个倒序相乘就可以了
被这个m要乘2坑了一波。。。调了半天才过样例
代码:
#include <bits/stdc++.h> using namespace std; #define N 200000 #define dob complex<double> const double pi=acos(-1.0); int r[N],sum[N],n,m,k,l; dob a[N],b[N]; void fft(dob *a,int o) { for (int i=0;i<n;i++) if (i>r[i]) swap(a[i],a[r[i]]); for (int i=1;i<n;i*=2) { dob wn(cos(pi/i),sin(pi*o/i)),x,y; for (int j=0;j<n;j+=(i*2)) { dob w(1,0); for (int k=0;k<i;k++,w*=wn) { x=a[j+k]; y=w*a[i+j+k]; a[j+k]=x+y,a[i+j+k]=x-y; } } } } void query() { for (n = 1; n <= m; n <<= 1) l++; for (int i=0;i<n;i++) r[i]=(r[i/2]/2)|((i&1)<<(l-1)); fft(a,1),fft(b,1); for (int i=0;i<n;i++) a[i]*=b[i]; fft(a,-1); for (int i=0;i<=m*2+10;i++) sum[i]=(a[i].real()/n+0.5); } int main() { freopen("noip.in","r",stdin); freopen("noip.out","w",stdout); std::ios::sync_with_stdio(false); cin>>m>>k; int x,now=0,ans=0; for (int i=0;i<m;i++) { cin>>x; now+=x; ans+=x*x; a[i]=x; } for (int i=m-1;i>=0;i--) { cin>>x; now-=x; ans+=x*x; b[i]=x; } int y=-now/m; int minn=1e9; for (int i=y-1;i<=y+1;i++) minn=min(m*i*i+2*i*now,minn); ans+=minn; int tmp=m; m*=2; query(); m=tmp; int maxn=sum[m-1]; for (int i=m;i<2*m;i++) maxn=max(sum[i]+sum[i-m],maxn); ans-=2*maxn; cout<<ans<<endl; return 0; }