欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

UVa 11300 Spreading the wealth

程序员文章站 2022-06-02 21:22:00
...

UVa 11300 Spreading the wealth


题解:

显然我们这里可以设一些方程,因为我们最后要让每一个人的金币数相等,那么我们现在可以假设每个人向左边的人给了多少金币,比如我们令x22号给1号了多少金币,当然,如果给的金币的数量是负的,那么实际上是12了金币。
那么我们显然可以得到如下方程
M=sum/n,即最后的每个人的值

A1x1+x2=M

A2x2+x3=M

A3x3+x4=M

......

An1xn1+xn=M

显然我们可以通过这些方程来进行求解,具体的方式是,我们把所有的x2,x3,x4等全部转化为x1
A1x1+x2=M>x2=MA1+x1=x1C1

这里我们让C1表示A1M
显然C数组我们可以处理出来,那么现在我们要最小化的显然是abs(x1)+abs(x2)+...+abs(xn)
所以把所有的xtmp转化为x1Ctmp1的形式,然后再进行最小化。
显然最后变成了abs(x1)+abs(x1C1)+...abs(x1Cn1)的最小值,显然我们只需要对C数组进行排序,然后选取其中点作为x1那么接下来的事情就是O(n)统计了。


代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
long long a[1000000+10],sum,M,c[1000000+10];
int n;
int main(){
    while(scanf("%d",&n)!=EOF&&n){sum=0;
        for(register int i=1;i<=n;i++)scanf("%lld",&a[i]),sum+=a[i];
        M=sum/n;c[0]=0;
        for(register int i=1;i<=n-1;i++)c[i]=c[i-1]+a[i]-M;
        sort(c+0,c+n);long long num=c[n/2];
        long long ans=0;for(register int i=0;i<=n-1;i++)ans+=abs(num-c[i]);
        printf("%lld\n",ans);
    }
    return 0;
}

UVa 11300 Spreading the wealth