zoukankan      html  css  js  c++  java
  • 【BZOJ1045】糖果传递

    题目

    有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。求使所有人获得均等糖果的最小代价。

    分析

    又是以前弄懂了,第二次做又不会了,下面自己手打一遍数学证明吧

    设 give[i]为第i个人给第i-1个人的糖果数量,a[i]为本身的糖果数量

    设均等的糖果数为 ave=sum/n

    则 a[1]+give[2]-give[1]=ave

    a[2]+give[3]-give[2]=ave

    ·········

    移项

    give[2]=give[1]+ave-a[1]

    give[3]=give[2]+ave-a[2]=give[1]+ave-a[1]+ave-a[2]

    可以观察到有一个 ave-a[i]的部分

    设b[i]=a[i]-ave 再设c[i]为b数组的前缀和

    则有 give[i]=give[1]-c[i-1]

    give[1]+give[2]+·······+give[n]=| c[0]-give[1] |+| c[1]-give[1] |+······+| c[n-1]-give[1] |

    相当于求数轴上的n个点到一定点的距离和的最小值

    就是初一数学学的, 所以give[1]取序列c的中位数即可

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define N 1001000
    #define ll long long
    ll n,sum,aver,minx,ans;
    ll a[N],c[N];
    inline void read(ll &x)
    {
        x=0;char ch=getchar();
        while(ch>'9'||ch<'0'){ch=getchar();}
        while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
    }
    int main()
    {
        read(n);
        for(int i=1;i<=n;i++)
            read(a[i]),sum+=a[i];
        aver=sum/n;
        for(int i=1;i<=n;i++)
            c[i]=c[i-1]-aver+a[i];
        sort(c+1,c+1+n);
        minx=c[(n+1)>>1];
        for(int i=1;i<=n;i++)
            ans+=abs(c[i]-minx);
        printf("%lld
    ",ans);
        return 0;
    }
    “Make my parents proud,and impress the girl I like.”
  • 相关阅读:
    Linux之Shell编程read读取控制台输入
    Linux之Shell编程while循环基本使用
    Linux之Shell编程for循环基本使用
    Linux之Shell编程case语句
    C语言 ##__VA_ARGS__
    C语言 __VA_ARGS__
    C语言 ##运算符
    C语言 __cplusplus
    C语言 #运算符
    C语言 extern “C”
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9637694.html
Copyright © 2011-2022 走看看