UVa 11300 Spreading the Wealth (数学推导-中位数)

UVa 11300 Spreading the Wealth

题目大意:

n个人围成环形,一个人可以给他相邻左右两边的人金币,求使得所有人最后的金币数相同的最少转手金币数,金币总数能被n整除.

题目分析:

这是一个环形的结构,可以尝试将其变成单向的, Xi 表示从i传到i+1的金币个数( Xn 表示从n传到1的金币个数),设每人最终的金币个数为 M ,则有Ai+Xi1Xi=M.

Ci=ni=1(AiM) ,则有
对于第1个人, A1+XnX1=MX1=XnC1
对于第2个人, A2+X1X2=MX2=XnC2

对于第n个人, An+Xn1Xn=M .然而这个式子却没有用,可以由前面n-1的式子推导得到,所以需要挖掘其他的信息.

由上述推导可知

ans=min{|Xn|+|XnC1|+...+|XnCn1|}

实际上当 Xn C 序列的中位数,有最小值.
原因在于,如果将Xn变成 Xn+1 ,则有

ans=ans+leftright
(left/right表示小于等于/大于 Xn C 的个数),

要使ans最小,则应当使得当前小于/大于Xn相同,所以 Xn C <script type="math/tex" id="MathJax-Element-19">C</script>序列中位数

代码:

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

typedef long long ll;
const int maxn=1000000+10;

ll A[maxn],C[maxn];

int main()
{
    int n;
    while(scanf("%d",&n)==1) {
        ll sum=0;
        for(int i=1;i<=n;i++) scanf("%lld",&A[i]),sum+=A[i];
        ll M=sum/n;
        for(int i=1;i<=n;i++) C[i]=C[i-1]+M-A[i];//求出C序列的值
        sort(C+1,C+n+1);
        ll x=C[n>>1],ans=0;//X为排序后C数组的中间值
        for(int i=1;i<=n;i++) ans+=abs(x-C[i]);
        printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值