【模板】 均分纸牌

传送门

题意

\(N\)个人拍成一排,每个人有\(C_{i}\)张牌,每个操作可以让任意一个人把一张牌给他旁边的一个人,求最小操作数使得每个人手中牌数相等

数据范围

\(1 <N < 100\)
\(1\leq C_{i}\leq 10000\)

题解

显然,只有牌总数\(sum\)能被\(N\)整除时才有解,本题保证了牌的总数是\(N\)的倍数所以一定有解
从第一个开始,

  • \(C_{1} > \frac{sum}{N}\),那么第一个人需要给第二个人\(C_{1}-\frac{sum}{N}\),即\(C_{2}\)加上\(\frac{sum}{N}\)

  • \(C_{1} < \frac{sum}{N}\),那么第一个人需要从第二个人拿\(\frac{sum}{N}-C_{1}\),即\(C_{2}\)减去\(\frac{sum}{N}\)

某个人被减成负数也没有关系,因为顺序不固定,那么最少操作就是:\(\sum_{i=1}^{N}\left|i \cdot \frac{s}{N}-G i\right|\),其中G是前缀和

如果假设 \(A_{i} = C_{i} - \frac{sum}{N}\),即一开始就让每个人手中的纸牌都减去\(\frac{sum}{N}\),并最终让每个人手里都恰好有\(0\)张,

答案显然不变为:\(\sum_{i=1}^{N}\left|S_{i}\right|\),其中\(S\)\(A\)的前缀和即\(S[i]=\sum_{j=1}^{i} A[j]\)

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define ll long long 
const int N=110;
int n;
int a[N];
int main(){
    scanf("%d",&n);
    int sum=0;
    rep(i,1,n+1) scanf("%d",&a[i]),sum+=a[i];
    int avg=sum/n;
    int ans=0;
    rep(i,1,n){
        if(a[i]>avg) a[i+1]+=a[i]-avg,ans++;
        else if(a[i]<avg) a[i+1]-=avg-a[i],ans++;
    }
    printf("%d\n",ans);
}
posted @ 2020-07-12 09:52  Hyx'  阅读(144)  评论(0编辑  收藏  举报