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;
}
posted @ 2021-03-09 21:32  牟翔宇  阅读(102)  评论(0编辑  收藏  举报