1. 程式人生 > >[BZOJ1045][HAOI2008]糖果傳遞 數學

[BZOJ1045][HAOI2008]糖果傳遞 數學

etc string for class pan cstring code getch 得到

題目鏈接:http://www.lydsy.com/JudgeOnline/problem.php?id=1045

我們假設每一個小朋友的代價為$x[i]$,每一次都從前面一個小朋友那裏拿,這種貪心跟紙牌均攤很像,想一想很容易理解。

設最後每個小朋友能得到$ave$個糖果,所以有$a[i]+x[i]-x[i+1]=ave$。

寫出每一個形如這樣的式子,可以消元得到$x[n]=x[1]+(n-1)*ave-sum[n-1]$。

我們令$c[i]=(i-1)*ave-sum[i-1]$,則我們最後所求為$Ans=\{\sum_{i=1}^n|x[1]-c[i]|\}_{min}$。

把$x[1]$和$c[i]$看成數軸上的點,可以證明當$x[1]$為$c[i]$的中位數時,取得$Ans$值。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 int inline readint(){
 8     int Num;char ch;
 9     while((ch=getchar())<0||ch>9) ;Num=ch-0;
10     while((ch=getchar())>=
0&&ch<=9) Num=Num*10+ch-0; 11 return Num; 12 } 13 int N; 14 ll a[1000010],b[1000010],ave; 15 int main(){ 16 N=readint(); 17 ll sum=0; 18 for(int i=1;i<=N;i++){ 19 a[i]=readint(); 20 sum+=a[i]; 21 } 22 ave=sum/N; 23 sum=0; 24 for(int i=1
;i<=N;i++){ 25 b[i]=ave*(i-1)-sum; 26 sum+=a[i]; 27 } 28 sort(b+1,b+1+N); 29 int mid=N+1>>1; 30 ll ans=0; 31 for(int i=1;i<=N;i++) ans+=abs(b[mid]-b[i]); 32 printf("%lld\n",ans); 33 return 0; 34 }

[BZOJ1045][HAOI2008]糖果傳遞 數學