bzoj1045(为什么网上那么多错误代码也能ac??)

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;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值