题目去洛谷
题意:
很清晰,n个人,每人有一些硬币硬币总数sum≡0(mod n),通过一些互相交换,使硬币数平均(即每人有相同个数的硬币)
分析:
还是有点思维含量的,我们这样想,我们其实就是要确定两两之间的硬币交换数量,设JHi表示第i个人和第i-1个人交换的硬币数量,特殊的JH1表示1和n交换的硬币的数量。其实我们只要确定了JH1,剩下的就都能确定了,我们先把交换的正负定义一下JHi为正表示i拿取,JHi为负表示i送出。
我们设JH1=x,然后求出JH2:JH1+mo1-JH2=ba(ba表示这几个数的平均数)JH2=JH1+mo1-ba。我们找到每个的JHn=JH1-()n,于是,答案就是,sum(abs(JHi-x)),然后就是确定x,其实写到这大家就都看出来了找到中位数,然后就好了。想明白后其实挺简单的。
补充:证明这样取JH1,JH2,JH3...不会卡住,如果卡住,那么给它的人一定要给他足够的,如果一个人两边给,就不会卡住,如果一直卡住,那么就有环,不成立。
代码:
#include <cstdio> #include <algorithm> using namespace std; const int maxn=1000000+10; long long a[maxn]; long long b[maxn]; int main(){ int n; while(~scanf("%d",&n)){ long long sum=0; for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); sum+=a[i]; } long long ba=sum/(long long)n; b[1]=0; for(int i=2;i<=n;i++) b[i]=b[i-1]+a[i-1]-ba; sort(b+1,b+1+n);//这么写可要想清楚,取了相反数。 long long z=b[(n+1)/2]; long long ans=0; for(int i=1;i<=n;i++) ans+=abs(b[i]-z); printf("%lld ",ans); } return 0; }