zoukankan      html  css  js  c++  java
  • P3723 [AH2017/HNOI2017]礼物

    直接拆式子:

    [sum_{i=1}^nleft(x_i-y_i+c ight)^2 ]

    [sum_{i=1}^n x_i^2-x_i imes y_i+c imes x_i-x_i imes y_i+y_i^2-c imes y_i+x_i imes c-c imes y_i+c^2 ]

    [sum_{i=1}^n x_i^2+y_i^2+c^2-2 imes x_i imes y_i+2cleft(x_i-y_i ight)-2 imes x_i imes y_i ]

    [left(sum_{i=1}^n x_i^2 ight)+left(sum_{i=1}^n y_i^2 ight)+cleft(2left(sum_{i=1}^n x_i-y_i ight)+nc ight)-2left(sum_{i=1}^n x_i imes y_i ight) ]

    为了取到最小值,前三项都是确定的。其中 (cin[1-m,m-1]),因为初始的差至多是 (m-1)

    将下标全部减一,也就是说我们只需要求出下式的最大值

    [sum_{i=0}^{n-1}x_i imes y_i ]

    按照套路翻转下标

    [sum_{i=0}^{n-1}x_{n-1-i} imes y_i ]

    尝试将 (x) 倍长然后再卷起来,举个例子:

    [x={x_0,x_1,x_0,x_1} ]

    [y={y_0,y_1} ]

    [z={x_0y_0,x_0y_1+x_1y_0,x_1y_1+x_0y_0,x_0y_1+x_1y_0,x_1y_1} ]

    可以发现第 (1)(2) 项恰好组成了所有旋转后的方案。也就是说第 (n-1)(2n-2) 项组成了所有旋转后的 (n) 种方案。

    取个 (max) 就好啦,时间复杂度 (Oleft(nlog n+m ight))

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define N 131073
    #define Db double
    #define Min(x,y)((x)<(y)?x:y)
    #define Max(x,y)((x)>(y)?x:y)
    #define For(i,x,y)for(i=x;i<=(y);i++)
    const Db PI=acos(-1.0);
    struct Complex
    {
    	Db x,y;
    	Complex(Db X=0.0,Db Y=0.0):x(X),y(Y){};
    	Complex operator+(Complex const&_)const
    	{
    		return Complex(x+_.x,y+_.y);
    	}
    	Complex operator-(Complex const&_)const
    	{
    		return Complex(x-_.x,y-_.y);
    	}
    	Complex operator*(Complex const&_)const
    	{
    		return Complex(x*_.x-y*_.y,x*_.y+y*_.x);
    	}
    }x[N],y[N];
    int tr[N];
    void FFT(Complex*f,int len,bool type)
    {
    	int i,p,j,now;
    	Complex tmp,ome,buf;
    	For(i,0,len-1)
    	if(i<tr[i])swap(f[i],f[tr[i]]);
    	for(p=2;p<=len;p<<=1)
    	{
    		now=p>>1;
    		ome=Complex(cos(2.0*PI/Db(p)),sin(2.0*PI/Db(p))*(type?-1.0:1.0));
    		for(j=0;j<len;j+=p)
    		{
    			buf=Complex(1.0,0.0);
    			For(i,j,j+now-1)
    			{
    				tmp=buf*f[i+now];
    				f[i+now]=f[i]-tmp;
    				f[i]=f[i]+tmp;
    				buf=buf*ome;
    			}
    		}
    	}
    	if(type)
    	For(i,0,len-1)f[i].x=round(f[i].x/Db(len));
    }
    int main()
    {
    	int n,m,i,tot=0,mn=INT_MAX,mx=INT_MIN;
    	scanf("%d%d",&n,&m);
    	For(i,1,n)scanf("%lf",&x[i].x);
    	For(i,1,n)scanf("%lf",&y[i].x),tot+=(x[i].x-y[i].x)*2.0;
    	For(i,1-m,m-1)mn=Min(mn,i*(tot+n*i));
    	For(i,1,n)
    	{
    		mn+=x[i].x*x[i].x+y[i].x*y[i].x;
    		x[i-1].x=x[i].x;
    		y[i-1].x=y[i].x;
    	}
    	For(i,0,(n-1)>>1)swap(x[i],x[n-1-i]);
    	y[n].x=0.0;
    	For(i,0,n-1)x[i+n].x=x[i].x;
    	m=1;
    	while(m<n<<1)m<<=1;
    	For(i,0,m-1)tr[i]=tr[i>>1]>>1|(i&1?m>>1:0);
    	FFT(x,m,0),FFT(y,m,0);
    	For(i,0,m-1)x[i]=x[i]*y[i];
    	FFT(x,m,1);
    	For(i,n-1,(n-1)<<1)mx=Max(mx,x[i].x);
    	printf("%d",mn-(mx<<1));
    	return 0;
    }
    

    可以学到的技巧:

    • 一些跟下标有关的东西可以试试卷积。
  • 相关阅读:
    微信群之Java技术红包问答
    Java JPA 查询实体部分字段
    我的iphone6退货之路
    Simulated Annealing (模拟退火)
    ICML 2017 Reading (1): Combining Online and Offline Knowledge in UCT
    ICML 2017 Reading
    NIPS 2014
    Gumbel-Max trick, Perturb and MAP and more
    ICML 2014
    非常有趣的JavaScript游戏
  • 原文地址:https://www.cnblogs.com/May-2nd/p/14165268.html
Copyright © 2011-2022 走看看