C-平分游戏

先不考虑是隔$k$个人,直接当成每次逆时针加$k$。那么原图中的$n$个人划分为若干个环,每个环都是独立的,这里取一个四元环继续讲解。

假设四个人原先有的钱为$S_i$,逆时针收到的钱为$x_i$(负数即反向),需要达到平均值$A$,那么有
$$
\left\{
\begin{array}{c}
S_1+x_1-x_2=A \\
S_2+x_2-x_3=A \\
S_3+x_3-x_4=A \\
S_4+x_4-x_1=A
\end{array}
\right.
$$
一行一行加,解得:
$$
\left\{
\begin{array}{c}
x_1=&x_1 &\triangleq x_1-y_1 \\
x_2=&x_1-(A-S_1) &\triangleq x_1-y_2 \\
x_3=&x_1-((A-S_1)+(A-S_2)) &\triangleq x_1-y_3 \\
x_4=&x_1-((A-S_1)+(A-S_2)+(A-S_3)) &\triangleq x_1-y_4
\end{array}
\right.
$$
这个环所需要的总时间为$T=|x_1|+|x_2|$ $+|x_3|+|x_4|$ $=|x_1-y_1|+|x_1-y_2|$ $+|x_1-y_3|+|x_1-y_4|$,由绝对值数形结合的知识可知当$x_1$取$y_i$的中位数(不计平均)时该式最小。
对于这道题,可以先求出总的平均值$A$,然后每个环都用这个$A$列方程和验证,答案累加即可。
最后说一下$k$的问题,题意不是很清晰,最终确定隔$n-1$个人是可以的(相当于相邻),隔$n$个人是不可以的(没有实际意义)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1000010;
ll s[N];
bool vis[N];
int main()
{
int n,k;
scanf("%d%d",&n,&k);
++k;
ll sum=0;
for (int i=0;i<n;i++) {
scanf("%lld",&s[i]);
sum+=s[i];
}
if (sum%n) {
puts("gg");
return 0;
}
ll A=sum/n,ans=0;
int cnt=0;
for (int i=0;i<n;i++) {
cnt+=(s[i]==A);
}
if (cnt==n) {
puts("0");
return 0;
}
if (k>n) {
puts("gg");
return 0;
}
bool good=true;
for (int i=0;i<n;i++) {
if (vis[i]) continue;
int j=i;
ll tmp=0;
vector<ll> ve;
do {
vis[j]=true;
tmp+=A-s[j];
ve.push_back(tmp);
j=(j+k)%n;
} while (j!=i);
if (tmp) {
good=false;
break;
}
sort(begin(ve),end(ve));
ll x=ve[ve.size()/2];
for (auto y:ve) {
ans+=abs(x-y);
}
}
if (!good) {
puts("gg");
} else {
printf("%lld\n",ans);
}
return 0;
}