【模板】 均分纸牌

传送门

题意

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

数据范围

(1 <N < 100)
(1leq 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 ight|),其中G是前缀和

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

答案显然不变为:(sum_{i=1}^{N}left|S_{i} ight|),其中(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
",ans);
}
原文地址:https://www.cnblogs.com/hhyx/p/13287287.html