AtCoder Regular Contest 175 E Three View Drawing

洛谷传送门

AtCoder 传送门

下文令 \(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;
}

posted @ 2024-03-29 16:50  zltzlt  阅读(6)  评论(0编辑  收藏  举报