题目:https://www.nowcoder.com/acm/contest/90/C
题意:
n个人围坐一个圆,每人初始a[i]个硬币;
每秒钟有且仅有一个人把一个硬币给另一个人,两人必须相隔k人;
求最少多少秒后,使得每人手中硬币数相等。
分析:
设其中num个人是可以相互给硬币的(组成一个小环),如下
(1)–X1–>(2)–X2–>(3)–X3–>……–Xnum-1–>(num)–Xnum–>(1)
其中,Xi代表i给i+1多少枚硬币,可以为负;
设每个人最后手中的硬币数为M,得到等式:
a[1]+x6-x1=M;
a[2]+x1-x2=M;
a[3]+x2-x3=M;
.
.
a[num]+X(num-1)-Xnum=M;
即:
x1=x1;
x2=x1-(M-a[2]);
x3=x1-(M-a[2]-a[3]);
.
.
xnum=x1-(M-a[2]-a[3]-…-a[num]);
即:
xi=x1-(M-∑aj); (2<=j<=i)
所求即为:
|x1|+|x2|+…+|xnum|
实际就是x1到(M-∑aj)的距离;
求中位数,即可得到。
注意:认为k==n使不能传递硬币(谁tm知道题意是这样的,擦)。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int tmax=1e6+5;
int n,k,p[tmax],num;
ll a[tmax],M,sum[tmax],x,ans;
bool v[tmax];
int main()
{
cin>>n>>k;
int i,j;
for(i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
M+=a[i];
}
if(M%n>0)
{
printf("gg");
return 0;
}
M/=n;
if(k==n)
{
for(i=1;i<=n;i++)
if(a[i]!=M)
{
printf("gg");
return 0;
}
}
for(i=1;i<=n;i++)
{
if(v[i]==true) continue;
num=0;
sum[1]=0;
for(j=i;v[j]==false;)
{
v[j]=true;
p[++num]=j;
j=(j+k+1)%n;
if(j==0) j=n;
}
for(j=2;j<=num;j++)
sum[j]=sum[j-1]+a[p[j]];
if(sum[num]+a[p[1]]!=num*M)
{
printf("gg");
return 0;
}
for(j=2;j<=num;j++)
sum[j]=(j-1)*M-sum[j];
sort(sum+1,sum+1+num);
x=sum[(num+1)/2];
for(j=1;j<=num;j++)
ans+=abs(x-sum[j]);
}
printf("%lld",ans);
return 0;
}