zoukankan      html  css  js  c++  java
  • [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
    ",ans+sum1);
    60   return 0;
    61 }
  • 相关阅读:
    sqlserver中判断表或临时表是否存在
    Delphi 简单方法搜索定位TreeView项
    hdu 2010 水仙花数
    hdu 1061 Rightmost Digit
    hdu 2041 超级楼梯
    hdu 2012 素数判定
    hdu 1425 sort
    hdu 1071 The area
    hdu 1005 Number Sequence
    hdu 1021 Fibonacci Again
  • 原文地址:https://www.cnblogs.com/D-O-Time/p/7954847.html
Copyright © 2011-2022 走看看