[HNOI2017]礼物
因为可以加上一个常数C,说是非负整数,但其实A手环加上,就等于B手环减去,于是把m范围扩充到[-100,100]即可。
然后所求变为:
$$\sum (x_i-y_i+C)$$
接着拆开,可以得到:
$$\sum(x_i^2+y_i^2+C^2)+2*C*\sum(x_i-y_i)+2*\sum(x_i*y_i)$$
然后发现这些有常量,可变的C所对应的x和y是常数,而与顺序有关的xi*yi又是与C无关的。所以我们可以先求出的最大值xi*yi。如果我们将B手环在输入之后反转一下,可以发现当翻转前A与B发生错位之时,每一个错位都可以对应反转之后的B与A的FFT的乘积的各个项的系数。
然后再枚举C从[-m,m]那么答案就出来了。
不会FFT的就去学吧。
1 #include<cmath> 2 #include<cstdio> 3 #include<complex> 4 #include<iostream> 5 #include<algorithm> 6 #define C complex<double> 7 #define pf(a) ((a)*(a)) 8 using namespace std; 9 const int MAXN=1000000,INF=0x3f3f3f3f; 10 const double pi=acos(-1.0); 11 int n,m,L,G,Max,Val,ans=INF,sum1,sum2; 12 int R[MAXN],V[MAXN]; 13 C A[MAXN],B[MAXN]; 14 inline int gi(){int res; scanf("%d",&res); return res;} 15 void FFT(C *a,int p) 16 { 17 for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]); 18 for(int i=1;i<n;i<<=1) 19 { 20 C wn(cos(pi/i),sin(p*pi/i)),x,y; 21 for(int j=0;j<n;j+=(i<<1)) 22 { 23 C w(1,0); 24 for(int k=0;k<i;k++,w*=wn) 25 { 26 x=a[j+k],y=w*a[j+k+i]; 27 a[j+k]=x+y; 28 a[j+k+i]=x-y; 29 } 30 } 31 } 32 } 33 int main() 34 { 35 freopen("gift.in","r",stdin); 36 freopen("gift.out","w",stdout); 37 n=gi();Max=gi(); n--; 38 for(int i=0;i<=n;i++)A[i]=gi(); 39 for(int i=0;i<=n;i++)B[i]=gi(); 40 for(int i=0;i<=n;i++) 41 { 42 sum1+=pf(A[i].real())+pf(B[i].real()); 43 sum2+=A[i].real()-B[i].real(); 44 } 45 m=n+n; reverse(B,B+n+1); 46 for(n=1;n<=m;n<<=1)L++;L--; 47 for(int i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L); 48 FFT(A,1); FFT(B,1); 49 for(int i=0;i<=n;i++)A[i]*=B[i]; 50 FFT(A,-1); 51 for(int i=0;i<=m;i++)V[i]=(int)(A[i].real()/n+0.5); 52 n=m/2; Val=V[n]; 53 for(int i=0;i<=n-1;i++) 54 if(Val<V[i]+V[n+i+1]) 55 Val=V[i]+V[n+i+1]; 56 Val*=2; 57 for(int c=-Max;c<=Max;c++) 58 ans=min(ans,sum2*2*c+(n+1)*c*c-Val); 59 printf("%d\n",ans+sum1); 60 return 0; 61 }