[BZOJ1045][HAOI2008]糖果傳遞 數學
阿新 • • 發佈:2017-10-05
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]糖果傳遞 數學