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 }
  • 相关阅读:
    大小端判断
    引用计数
    STL_ALGORITHM_H
    书单一览
    GIT版本控制系统(二)
    JS随机数生成算法
    STL学习笔记--临时对象的产生与运用
    乱序优化与GCC的bug
    你的灯亮着吗?
    交换机和路由器
  • 原文地址:https://www.cnblogs.com/D-O-Time/p/7954847.html
Copyright © 2011-2022 走看看