您的位置:首页 > 其它

UVa 11300 Spreading the Wealth 分金币

2015-06-23 20:57 357 查看
题意:n个人坐成一圈,编号依次为1-n,1和n是邻座。每个人有一定数量的金币,保证金币总数能被n整除。现在要求每个人给相邻的两人各若干金币,使得所有人都持有等量金币。求所有人给出的金币的数量和的最小值。

这是一道数学题。我们这样考虑,对于某两个相邻的人,如果第一个人给了第二个人x个金币,而第二个人又给了第一个人y个金币,这相当于第一个人给了第二个人x-y个金币(当然,是负数也无妨,是负数相当于他得到金币)而第二个人没有给第一个人任何金币。如此看来,我们不妨设每个人只给他的下一个人金币(是负数就表示得到)。题目说了总数一定是n的倍数,则每个人最后的金币数为定值,不妨记为average。下面我们设每个人开始有Ai个金币,第i个人给第i + 1个人Xi个金币。我们可以列出方程:

A1 + X0 - X1 = average

A2 + X1 - X2 = average

A3 + X2 - X3 = average

......

An-1 + Xn-2 - Xn-1 = average

A0 + Xn-1 - X0 = average

当然最后这个方程并没有用,因为前n - 1个方程相加就可以得到这个方程

但是我们可以把每个Xi都用X1表示出来

下面对上述方程进行形如Xi = f(X1)形式的变形,可以得到:

X1 = X0 + A1 - average

X2 = X1 + A2 - average = X0 + A1 + A2 - 2*average

X3 = X2 + A3 - average = X0 + A1 + A2 - 3*average

......

Xn-1 = Xn-2 + An-1 - average = X0 + A1 + A2 + ...... + An-1 - average

若定义一个S数列,其中S0 = 0,Si = Si-1 + average - Ai,则有Si = X0 + A1 + A2 + ...... + Ai - i*average

代入上述变形即可得到

Xi = X0 - Si

于是我们要求的即为sigma(Xi) = sigma(X0 - Si)

这个式子的几何意义非常明显,就是给定数轴上的若干点S0、S1、S2 ...... Sn-1,要找一个点到这些点的距离和最小。

找这个点很简单。我们随便找个点x,设给定的若干点里位于x左边的点有L个,位于右边的点有R个,不放假设L > R,那么我们将x往左移动d个距离(不跨过x左边第一个点),则总距离和减少了L*d,增加了R*d,而L*d > R*d,所以移动后的点x更优。当L < R的时候亦是如此。因此我们必须保证对于找到的点x,位于x左边的给定的点和位于x右边的给定的点一样多。

于是我们将S0 ~ Sn-1排序后,要找的这个点一定是中间点(若总数是奇数则是正中间那个点,若总数是偶数则是中间两个点之间的任何一个点)。于是我们取这个点为Sn/2即可(对于总数是奇数或偶数都适用)。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#define ll long long
using namespace std;

const int MAX = 1000005;
int n;
ll money[MAX], sum[MAX];

void input()
{
for(int i = 0; i < n; i++)
scanf("%d", &money[i]);
}

void solve()
{
ll average = 0;
for(int i = 0; i < n; i++)
average += money[i];
average /= n;
sum[0] = 0;
for(int i = 1; i < n; i++)
sum[i] = sum[i - 1] + average - money[i];
sort(sum, sum + n);
int mid = n/2;
ll ans = 0;
for(int i = 0; i < n; i++)
ans += labs(sum[mid] - sum[i]);
printf("%lld\n", ans);
}

int main()
{
while(scanf("%d", &n) != EOF)
{
input();
solve();
}
return 0;
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: