AtCoder Regular Contest 175 E Three View Drawing
下文令 \(m\) 为原题面的 \(k\)。
题目条件很奇怪,考虑有没有什么比较好用的策略。
发现对于任意一个三元组 \((a, b, c)\),其中 \(a, b, c\) 不全相等,那么同时添加 \((a, b, c), (b, c, a), (c, a, b)\),\(\{(x_i, y_i)\}, \{(y_i, z_i)\}, \{(z_i, x_i)\}\) 三个集合都会同时添加 \((a, b), (b, c), (c, a)\)。特别地,对于三元组 \((a, a, a)\),添加它后三个集合都会同时添加 \((a, a)\)。所以如果原来的合法,那么添加后也合法。
所以考虑找出尽可能多组 \(\{(a, b, c), (b, c, a), (c, a, b)\}\)。发现可以直接令 \(a + b + c \equiv 0 \pmod n\)。这样若 \(n \bmod 3 = 0\),除了 \((0, 0, 0), (\frac{n}{3}, \frac{n}{3}, \frac{n}{3}), (\frac{2n}{3}, \frac{2n}{3}, \frac{2n}{3})\),其他 \(n^2 - 3\) 个 \((a, b, (-a - b) \bmod n)\) 都恰好在一个“组”内。若 \(n \bmod 3 \ne 0\),除了 \((0, 0, 0)\),其他 \(n^2 - 1\) 个 \((a, b, (-a - b) \bmod n)\) 都恰好在一个“组”内。
所以一个想法是把 \(m\) 分成 \(3 \left\lfloor\frac{m}{3}\right\rfloor\) 和 \(m \bmod 3\) 两部分,前者就直接取 \(\left\lfloor\frac{m}{3}\right\rfloor\) 组 \((a, b, c), (b, c, a), (c, a, b)\),后者就取 \(m \bmod 3\) 组 \((a, a, a)\)。
但是你发现你在 \(n \bmod 3 \ne 0\) 且 \(m \bmod 3 = 2\) 的时候寄了,因为此时形如 \((a, a, a)\) 的三元组只有一个 \((0, 0, 0)\),但是上面的方法需要 \(2\) 个。发现此时 \(m \le n^2 - 2\),所以可以直接把一组 \((a, b, c), (b, c, a), (c, a, b)\) 拆掉,比如拆 \((1, 1, (-2) \bmod 3)\),把它变成 \((1, 1, 1)\) 即可。
code
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;
const int maxn = 510;
int n, m;
bool vis[maxn][maxn];
void solve() {
scanf("%d%d", &n, &m);
bool fl = 0;
if (n % 3 && m % 3 == 2) {
vis[1][1] = 1;
fl = 1;
}
for (int i = 0; i < n && m >= 3; ++i) {
for (int j = 0; j < n && m >= 3; ++j) {
int k = (n * 2 - i - j) % n;
if ((i == j && i == k) || vis[i][j] || vis[j][k] || vis[k][i]) {
continue;
}
vis[i][j] = vis[j][k] = vis[k][i] = 1;
printf("%d %d %d\n%d %d %d\n%d %d %d\n", i, j, k, j, k, i, k, i, j);
m -= 3;
}
}
if (n % 3 == 0) {
for (int i = 0; i < m; ++i) {
printf("%d %d %d\n", n / 3 * i, n / 3 * i, n / 3 * i);
}
} else {
if (m) {
puts("0 0 0");
}
if (m > 1 && fl) {
puts("1 1 1");
}
}
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}