有 \(n\) 名选手参加一场比赛,编号为 \(1 \sim n\) 。规则为:
- 选手 \(1\) 和选手 \(2\) 比赛
- 第 \(1\) 轮胜者胜者与选手 \(3\) 比赛;
- 第 \(2\) 轮胜者与选手 \(4\) 比赛
- \(\cdots\)
- 第 \(n - 2\) 轮胜者与选手 \(n\) 比赛。
若能构造一组比赛结果 \(b\) ,\(b_i\) 代表第 \(i\) 轮获胜的选手编号,输出任意一组。且只知道以下信息:
- 任一参赛选手要么胜利 \(x\) 轮要么胜利 \(y\) 轮。
诈骗题,\(x\) \(y\) 一定有且仅有是 \(0\) 。
观察一:每轮一输一赢,则 \(\sum_{i}^{n} win_{i} = \sum_{i}^{n} lose_{i}\)
观察二:有 \(n - 1\) 个参赛选手会输一次,则 \(\sum_{i}^{n} lose_{i} = n - 1\) ,即 \(\sum_{i}^{n} win_{i} = n - 1\) 。根据鸽巢原理,(至少)存在一个人赢不了,保证 \(min(x, y) = 0\) 。
观察三:显然(至少)存在一个人能赢,保证 \(max(x, y) > 0\) 。
观察四:共 \(n - 1\) 轮,每 \(max(x, y)\) 轮分为一组。
观察五:每 \(max(x, y)\) 轮中,只有该组第一轮的俩人之一赢 \(max(x, y)\) 轮,其他人全输。
于是问题解决:
若 \(min(x, y) \neq 0\) 或者 \(max(x, y) \nmid n - 1\) 则无解。
- 判断 \(x \mid y\) 时若用 \(y \% x\) 判断,当 \(x = 0\) 时出现运算错误。可用 \(gcd(x, y)\) 判断,若满足则 \(g = x\)。
否则,不妨让每 \(max(x, y)\) 轮一组,每组的第二个选手赢。因为从第二组开始,第一个人必须输。
枚举 \(\frac{n - 1}{max(x, y)}\) 轮,每轮 \(max(x, y)\) 次,时间复杂度 \(O(n)\) 。
view
#include <bits/stdc++.h>
long long gcd(long long a, long long b) {return b?gcd(b,a%b):a;}
void solve() {
int n, x, y; std::cin >> n >> x >> y;
if (std::min(x, y) != 0 || gcd(n-1, std::max(x, y)) != std::max(x, y)) {
std::cout << -1 << '\n';
}
else {
for (int i = 1; i * std::max(x, y) < n; i++)
for (int j = 1; j <= std::max(x, y); j++)
std::cout << (i - 1) * std::max(x, y) + 2 << " \n"[i == n - 1 && j == std::max(x, y)];
}
}
signed main() {
int _ = 1; std::cin >> _;
while (_--) solve();
return 0;
}