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;
}
posted @ 2025-04-24 22:05  CJzdc  阅读(25)  评论(0)    收藏  举报