把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P2512 [HAOI2008]糖果传递

题面传送门
又是数学题。
\(a_i\) 为本来钱数,\(b_i\) 为给后一个人多少钱,\(m\) 为平均分的钱数。
则: \(a_1-b_1+b_2=m\)
\(a_1-b_1+b_2=m\)
\(b_2=b_1-(a_1-m)\)
\(a_2-b_2+b_3=m\)
\(b_3=2m-a_2+b_1-a_1\)
所以 可得\(b_3=b_1-(a_1-m)-(a_2-m)\)
以此类推,\(b_i=b_1-\sum\limits_{j=1}^{i-1}{(a_j-m)}\)
所以原题变为求\(\sum\limits_{i=1}^{n}{\left|b_1-\sum\limits_{j=1}^{i-1}{(a_j-m)}\right|}\)第二重循环可以用前缀和优化,那么只要让\(b_1\) 最小就 行了。找中点呗!
代码实现:

#include<cstdio>
#include<cmath>
#include<algorithm>
#define abs(x) ((x)>0?(x):-(x))
using namespace std;
int m,n;
long long ans,tot,pus,now,q[1000039],a[1000039];
inline void read(long long  &x){
   char s=getchar();x=0;
   while(s<48||s>57) s=getchar();
   while(s>=48&&s<=57) x=(x<<3)+(x<<1)+(s^48),s=getchar();
}
int main(){
   register int i;
   scanf("%d",&n);
   for(i=1;i<=n;i++)read(a[i]),ans+=a[i];
   m=ans/n;
   for(i=1;i<=n;i++) a[i]-=m,q[i]=q[i-1]+a[i];
   sort(q+1,q+n+1);
   now=q[(int)ceil(n*1.0/2)];
   for(i=1;i<=n;i++) tot+=abs(q[i]-now);
   printf("%lld",tot);
   return 0;
}
posted @ 2020-03-29 18:24  275307894a  阅读(41)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end