1045 糖果传递
设xi为第i个人向第i+1个人传递的糖果数,那么就有等式:a[i]+x(i-1)-x(i)=ave
即:a[2]+x1-x2=ave -> x2=a[2]+x1-ave=x1-c1
a[3]+x2-x3=ave -> x3=a[3]+x2-ave=x1-c2
c1=ave-a[1];c2=c1+ave-a[2];… cn=c(n-1)+ave-a[n-1] (网上很多代码递推到c(n))
所以传递次数=abs(x1)+abs(x2)+…+abs(xn)
=abs(x1)+abs(x1-c1)+…+abs(x1-c(n-1))
当x1,为0,c1,…,c(n-1)的中位数时,传递次数最小 (网上很多取的是c1...cn的中位数)
我就很纳闷,为什么递推到cn取c1...cn的中位数也能ac
以下为正确思想的ac代码
/**************************************************************
Problem: 1045
User: syh0313
Language: C++
Result: Accepted
Time:2712 ms
Memory:16916 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using
namespace
std;
const
int
maxn=1000010;
int
n;
long
long
a[maxn],sum,ave,now,ans,b[maxn];
int
main()
{
scanf
(
"%d"
,&n);
for
(
int
i=1;i<=n;i++)
scanf
(
"%lld"
,&a[i]),sum+=a[i];
ave=sum/(
long
long
)n;
for
(
int
i=2;i<=n;i++) b[i]=b[i-1]+a[i]-ave;
sort(b+1,b+n+1);
int
now=b[n/2];
for
(
int
i=1;i<=n;i++) ans+=
abs
(now-b[i]);
printf
(
"%lld\n"
,ans);
return
0;
}
以下为递推到cn取c1...cn的中位数的ac代码(网上这种居多,但是思想是不对的)
/**************************************************************
Problem: 1045
User: syh0313
Language: C++
Result: Accepted
Time:2744 ms
Memory:16916 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using
namespace
std;
const
int
maxn=1000010;
int
n;
long
long
a[maxn],sum,ave,now,ans,b[maxn];
int
main()
{
scanf
(
"%d"
,&n);
for
(
int
i=1;i<=n;i++)
scanf
(
"%lld"
,&a[i]),sum+=a[i];
ave=sum/(
long
long
)n;
for
(
int
i=1;i<=n;i++) b[i]=b[i-1]+a[i]-ave;
sort(b+1,b+n+1);
int
now=b[n/2];
for
(
int
i=1;i<=n;i++) ans+=
abs
(now-b[i]);
printf
(
"%lld\n"
,ans);
return
0;
}