P9837 汪了个汪
题目可以看成,用 \(1,2,\cdots,n\) 个点的链,覆盖一个完全图,且起点两两不同。
当 \(n\) 为偶数时,可以通过 ZigZag Pattern 构造出 \(\frac{n}{2}\) 条 \(n\) 个点的链。
具体地,对于一个起点 \(x\),我们按照 \(x,x-1,x+1,x-2,x+2,\cdots,x-\frac{n}{2}\) 构造一条链。称以 \(i\) 为起点构造的是第 \(i\) 条链,其中 \(1\le i\le\frac{n}{2}\)。
注意到,这 \(\frac{n}{2}\) 条链的端点两两不同,所以我们对于第 \(i\) 条链,拆成前 \(i\) 个点的一条链和后 \(n-i+1\) 个点的链。不难发现这样构造是合法的。
对于 \(n\) 为奇数,这时考虑构造 \(n+1\) 个点的 ZigZag Pattern。
可以发现,\(n+1\) 在这 \(\frac{n+1}{2}\) 条链中的位置为 \(2,4,6,\cdots,n+1\)。那么把这些链中的 \(n+1\) 删掉后,就是一组合法的解。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int kN = 4005;
int n;
array<int, kN> path;
array<array<int, kN>, kN> p;
int main() {
// freopen("1.in", "r", stdin);
// freopen("1.out", "w", stdout);
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
int N = n + (n & 1);
for(int i = 1; i <= N / 2; i++) {
int cur = 0;
for(int j = 1, x = i; j <= N; j++) {
path[++cur] = x;
if(j & 1) x = (x - j + N - 1) % N + 1;
else x = (x + j - 1) % N + 1;
}
if(!(n & 1)) {
for(int j = 1; j <= i; j++) p[i][j] = path[j];
for(int j = 1; j <= n - i + 1; j++) p[n - i + 1][j] = path[n - j + 1];
}else {
for(int j = 1; j <= 2 * i - 1; j++) p[2 * i - 1][j] = path[j];
for(int j = 1; j <= N - 2 * i; j++) p[N - 2 * i][j] = path[N - j + 1];
}
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= i; j++) {
cout << p[i][j] << " \n" [j == i];
}
}
return 0;
}
浙公网安备 33010602011771号