• 「AH 2017/HNOI 2017」礼物


    题目链接

    戳我

    (Solution)

    应为我们可以将任意一个数列加上一个非负整数,即可以变为将一个数列加上一个整数(可以为负),我们将这个整数设为(z).所以要求的式子的变为:

    [sum_{i=1}^{n}(x_i-y_i+z)^2 ]

    首先来化简一下式子

    [sum_{i=1}^{n}(x_i-y_i+z)^2 ]

    [sum_{i=1}^{n}x_i^2+sum_{i=1}^{n}y_i^2+sum_{i=1}^{n}z_i^2+2zsum_{i=1}^{n}(x_i-y_i)-2sum_{i=1}^{n}x_i*y_i ]

    我们可以发现不管如何变化(sum_{i=1}^{n}x_i^2+sum_{i=1}^{n}y_i^2)的值都不会变.
    然后再看看(sum_{i=1}^{n}z_i^2+2zsum_{i=1}^{n}(x_i-y_i))显然这是一个关于(z)的二次函数.最小值可以(O(1))算出但是注意一下(z)必须是整数而且可以为负,所以需要将(-frac{x_i-y_i}{n})向上和向下取整并带入式子取最小值.
    所以我们现在只需要算出(2sum_{i=1}^{n}x_i*y_i)的最大值即可.
    这个如何去算,将(y)变成链,在进行一次(fft)在取一个最大值就好了

    (Code)

    #include<bits/stdc++.h>
    #define int long long
    #define rg register
    #define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
    using namespace std;
    int read(){
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
        return f*x;
    }
    const int N=3000001;
    const double pi=3.14159265358979323846;
    struct node {
        double x,y;
        node operator + (node z)const {
            return (node){x+z.x,y+z.y};
        }
        node operator - (node z)const {
            return (node){x-z.x,y-z.y};
        }
        node operator * (node z)const {
            return (node){x*z.x-y*z.y,y*z.x+x*z.y};
        }
    }f[N],g[N];
    int r[N],limit=1;
    void fft(node *a,int opt){
        for(int i=0;i<=limit;i++)
            if(i<r[i])
                swap(a[i],a[r[i]]);
        for(int i=1;i<limit;i<<=1){
            node w=(node){cos(pi/i),opt*sin(pi/i)};
            for(int j=0;j<limit;j+=i<<1){
                node l=(node){1,0};
                for(int k=j;k<j+i;k++){
                    node p=l*a[k+i];
                    a[k+i]=a[k]-p;
                    a[k]=a[k]+p;
                    l=l*w;
                }
            }
        }
    }
    int a[N],b[N];
    main(){
        int n=read(),k=read(),l=0,m=n,js=0,ans=0;
        for(int i=1;i<=n;i++)
            a[i]=f[i].x=read(),f[i+n].x=f[i].x,js+=a[i],ans+=a[i]*a[i];
        for(int i=1;i<=n;i++)
    		b[i]=read(),js-=b[i],ans+=b[i]*b[i];
    	reverse(b+1,b+n+1);
    	for(int i=1;i<=n;i++)
    		g[i].x=b[i];
    	int A=-floor(js*1.0/n),B=-ceil(js*1.0/n);
    	ans+=min(A*A*n+2*A*js,B*B*n+2*B*js);
    	n*=2;
    	while(limit<=n+m)
            limit<<=1,l++;
        for(int i=0;i<limit;i++)
            r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
        fft(f,1),fft(g,1);
        for(int i=0;i<=limit;i++)
            f[i]=f[i]*g[i];
        fft(f,-1);
    	int maxx=0;
        for(int i=m;i<=n+1;i++)
    		maxx=max((int)(f[i].x/limit+0.5),maxx);
    	printf("%lld",ans-2*maxx);
    }
    
    
  • 相关阅读:
    字符串函数使用与 Culture
    学习 Monitor使用
    Extjs的ajax实现
    linux下tomcat的安装及部署
    使用jquery插件实现打印指定区域功能
    hibernate的各种保存方式的区别 (save,persist,update,saveOrUpdte,merge,flush,lock)等
    html 树形菜单
    Ext4 修复对话框按钮翻译
    spring aop expression简单说明
    tomcat内存溢出的解决方法(java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError:)
  • 原文地址:https://www.cnblogs.com/hbxblog/p/10328890.html
Copyright © 2020-2023  润新知