問題概要

$\{1,2,\ldots ,N\}$の部分集合の組$(S_1,S_2,\ldots ,S_k)$について, 以下の条件を満たすものがあれば構築せよ.

  • $1,2,\ldots ,N$のうちどの整数も, $S_1,S_2,\ldots ,S_k$のうちちょうど 2 つに含まれる.
  • $S_1,S_2,\ldots ,S_k$のうちどの 2 つの集合をとっても, その共通成分はちょうど 1 つである.

制約

  • $1\leq N\leq 10^{5}$

考察

とりあえず, $N=1$について考えてみると, $S_1=S_2=\{1\}$として構築できる.

この$S_1,S_2$と共通成分を 1 つずつもつような$S_3$を作りたい.

ちょっと考えると, $S_1=\{1,\underline{2}\},S_2=\{1,\underline{3}\},S_3=\{\underline{2},\underline{3}\}$のように, 要素$2,3$を追加すれば良いと分かる.

この$S_1,S_2,S_3$と共通成分を 1 つずつもつような$S_4$を作りたい.

同様にして, $S_1=\{1,2,\underline{4}\},S_2=\{1,3,\underline{5}\},S_3=\{2,3,\underline{6}\},S_4=\{\underline{4},\underline{5},\underline{6}\}$のように, 要素$4,5,6$を追加すれば良い.

こんな感じで再帰的に構築できそうだという予想がつく.

このとき, $\displaystyle N = 1+2+\cdots+k=\frac{k(k+1)}{2}$より, 三角数でなければならない.

表

提出コード(Python3🐍)

n = int(input())
r = int((n * 2) ** .5)
if r * (r + 1) != n * 2:
    print('No')
    exit()
# nは三角数
res = [[] for i in range(r + 1)]
tmp = 0
for i in range(r - 1):
    for k in range(tmp, r - i + tmp):
        res[i].append(k + 1)
        res[i + k - tmp + 1].append(k + 1)
    tmp += r - i
res[-2].append(n)
res[-1].append(n)
print('Yes')
print(len(res))
for l in res:
    print(len(l), *l)