分金币

Posted zcxhaha

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分金币相关的知识,希望对你有一定的参考价值。

分金币

题目描述:

? 圆桌旁坐着n个人,每人有一定数量的金币,金币总数能被n整除。每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数相等。你的任务是求出被转手的金币数量的最小值。比如,n=4,且4个人的金币数分别为1,2,5,4时,只需转移4枚金币(第3个人给第2个人两枚金币,第2个人和第4个人分别给第1 个人1枚金币)即可实现每人手中的金币数目相等。

Input:

? 输入包含多组数据。每组数据第一行为整数n(n<=1 000 000),以下n行每行为一个整数,按逆时针顺序给出每个人拥有的金币数。输入结束标志为文件结束符(EOF)。

Output:

? 对于每组数据,输出被转手金币数量的最小值。输入保证这个值在64位无符号整数范围内。

Sample Input:

4 1 2 5 4

Sample Output:

4

题解:

假设M为每个人都拥有的金币数,每个人的金币变化是左右相邻的人对其造成的影响
假设这n个人构成一个环,先假设n=4,设(x1)指1号给4号多少金币,则(x2)代表2号给1号
多少金币,其他的由此类推下去。
则对于1号来说,他给了4号金币,则剩(a1-x1)
2号给了他金币,则剩(a1-x1+x2)
注意这里1号给4号和4号给1号的意义隐含在x1的符号里面(很巧妙),其他的类似
由于最后要等于M,然后就可以得方程了
(a1-x1+x2=M >> x2 = x1-(a1-M) = x1 - C1\ a2-x2+x3=M >> x3 = x2-(a2-M)=x1-a1-a2-2*M = x1 - C2\ a3-x3+x4=M >> x4 = x3-a1-a2-a3-3*M = x1 - C3\ an-xn+x1=M >> xn = x1 - C(n-1))
看到这里我们知道答案是所有xi的绝对值最小了
很显然这就转化为数轴上求一点x到(ci)距离和的最小值,然而这个点x其实就是序列(ci)(排
序后)的中位数,稍微想想应该知道

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 1000000+10;
long long A[maxn], C[maxn], tot, M;

int main(){
    int n;
    long long sum = 0;
    scanf("%d", &n);

    for(int i = 1; i <= n; ++i){
        scanf("%d", &A[i]);
        sum += A[i];
    }

    int arg = sum/n;

    C[0] = 0;

    for(int i = 1; i < n; ++i){
        C[i] = C[i-1] + A[i] - arg;
    }

    sort(C, C+n);

    long long x1 = C[n/2];
    long long ans = 0;

    for(int i = 0; i < n; ++i){
        ans += abs(x1 - C[i]);
    }

    printf("%lld
", ans);
    return 0;
}

以上是关于分金币的主要内容,如果未能解决你的问题,请参考以下文章

分金币 [CQOI 2011] [BZOJ 3293]

bzoj3293[Cqoi2011]分金币

[BZOJ3293] [Cqoi2011] 分金币 (贪心)

蓝书第一章 例题3 分金币

BZOJ-3293&1465&1045分金币&糖果传递×2 中位数 + 乱搞

有趣的海盗分金币问题,不学点算法都不配当个海盗了