zoukankan      html  css  js  c++  java
  • 【模板】 均分纸牌

    传送门

    题意

    (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);
    }
    
  • 相关阅读:
    获取字符串出现的次数
    手机号码正则表达式验证
    DOM: EVENT FLOW
    AsyncCallback 异步回调委托
    高德地图
    我的json
    Arrow function restore
    constructor&object 的联系与对比
    for each/in/of的解释and example
    program发展史及以后预测
  • 原文地址:https://www.cnblogs.com/hhyx/p/13287287.html
Copyright © 2011-2022 走看看