CF1487-C. Minimum Ties
题意
一个足球比赛有n只队伍参加,这n只队伍会两两进行比赛,一共进行\(\frac{n\times(n-1)}{2}\)场比赛。
每一场比赛获胜的一方会得到3分,失败的一方不得分,若平局则两方各得一分。
现在让你找出一种方案,方案中你可以胜利、失败和平局,使得所有队伍的得分相同且平局的数量最少。
思路
首先先考虑什么情况下不会出现平局。一共有\(\frac{n\times(n-1)}{2}\)场比赛,如果每个人平均下来都能够赢得\(\frac{\frac{n\times(n-1)}{2}}{n}=\frac{n-1}{2}\)场比赛,那么就不会有平局。但是\(\frac{n-1}{2}\)不一定是整数,而实际上要求它是整数,所以第一个条件就是:\(\frac{n-1}{2}\)是个整数,换言之\(n\)需要是个奇数。
接着上面来,如果\(n\)是个偶数呢?那么在每个人平均赢得\(\frac{n-1}{2}\)(向下取整,即\(\frac{n-2}{2}\))之后,还有\(\frac{n\times(n-1)}{2}-\frac{n-2}{2}\times n=\frac{n}{2}\)场比赛,那么这\(\frac{n}{2}\)场比赛安排平局就可以使得所有队伍的分数相同。
具体的分配方式,举一个例子,假设\(n=5\),下面括号\((a,b)\)表示\(a\)赢\(b\):
\((1,2)(2,3)(3,4)(4,5)(5,1);(1,3)(2,4)(3,5)(4,1)(5,2);(1,4)(2,5)(3,1)(4,2)(5,3)\)
就相当于形成环来赢得比赛,a赢b,b赢c,c赢a。
以上思路的严格证明暂时没有想出来,但是多个例子都验证了上述结论。
AC代码
#include <cstdio>
#include <cstring>
#include <map>
#include <iostream>
#define pii pair<int, int>
#define mp(a, b) make_pair(a, b)
#define fr first
#define sc second
std::map<std::pii, int>res;
void solve() {
res.clear();
int n;
scanf("%d", &n);
int t = (n - 1) / 2;
for (int i = 1; i <= t; i++) {
for (int j = 0; j < n; j++) {
int tt = (j + i) % n;
std::pii pr = std::mp(j, tt);
if (j > tt) {
std::swap(pr.fr, pr.sc);
res[pr] = -1;
} else {
res[pr] = 1;
}
}
}
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (!res.count(std::mp(i, j))) {
printf("0 ");
} else {
printf("%d ", res[std::mp(i, j)]);
}
}
}
printf("\n");
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}