zoukankan      html  css  js  c++  java
  • BZOJ1045

    传送门:BZOJ1045

    结论题。

    ixiave
    aixi+xi1=ave

    i=1n|xi|

    能够构造出
    a1x1+x2=ave
    a2x2+x3=ave
    a1x3+x4=ave
    …..
    anxn+x1=ave

    这个方程组有n个方程和n个变量,但显然。最后一个方程式无意义。


    于是考虑:
    a1x1+x2=avex2=ave+x1a1
    a2x2+x3=avex3=ave+x2a2=2×avea1a2+x1
    a3x3+x4=avex3=3×avea1a2a3+x1

    anxn+x1=ave

    这仅仅要自己计算一下就能够明确,记ci=(ij=1aj)i×ave。于是有
    x2=x1c1
    x3=x1c2
    ……
    i2,xi=x1ci1
    于是最小化的目标函数就是

    |x1|+i=1n1|x1ci|=|x10|+i=1n1|x1ci|

    也就是说,给出数轴上的点(0,c1,c2,c3...cn1)y,y
    y

    完毕推导后做法还是非常优雅的。

    代码上的小细节见下。

    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    using namespace std;
    
    int n;
    int a[1000005];
    int c[1000005];
    long long ave;
    
    void Solve()
    {
        for(int i=2;i<=n;i++)
            c[i]=c[i-1]+a[i]-ave;
        sort(c+1,c+n+1);
        long long ans=0;
        int j=(1+n)/2;
        for(int i=1;i<=n;i++)
            ans+=abs(c[j]-c[i]);
        cout<<ans;
    }
    
    void Readdata()
    {
        freopen("loli.in","r",stdin);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
            ave+=a[i];
        ave/=n;
    }
    
    void Close()
    {
        fclose(stdin);
        fclose(stdout);
    }
    
    int main()
    {
        Readdata();
        Solve();
        Close();
        return 0;
    }
  • 相关阅读:
    PL/SQL 记录集合IS TABLE OF的使用
    PL/SQL 触发器简介
    plsql 显式游标
    MySQL的基本知识 -- 命令
    排序算法--桶排序
    在C++中实现字符串分割--split
    第一篇献给小驰驰
    解决windows管理员已阻止你运行此应用问题
    centos 7.3 快速安装ceph
    python中int的功能简单介绍
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7072574.html
Copyright © 2011-2022 走看看