Official

C - Circular Tree Embedding Editorial by evima


First, we transform the \(M\) permutations appropriately so that \(P^1=(1,2,\ldots,N)\). Let \(\mathrm{inv}\) be the inverse permutation of \(P^1\). Simultaneously replacing \(P^i_j\to P^i_{\mathrm{inv}_j}\) does not change the answer. From now on, we assume \(P^1=(1,2,\ldots,N)\).

Also, since \(P^i\) being a good permutation is equivalent to \(((P^i_1+k\ \mathrm{mod} \ N) + 1,(P^i_2+k\ \mathrm{mod} \ N) + 1,\ldots,(P^i_N+k\ \mathrm{mod} \ N) + 1)\) being a good permutation, we set \(P^i_1=1\).

Hereafter, we consider trees as rooted trees with vertex \(1\) as the root. We call rooted trees for which \(P^1,P^2,\ldots,P^M\) are all good permutations wonderful rooted trees.

For a permutation \(Q\) with \(Q_1=1\), \(Q\) being a good permutation for rooted tree \(T\) is equivalent to the following:

  • For any subtree of \(T\), if we let \(V\) be the vertex set contained in that subtree, then \(V\) can be appropriately arranged to form a contiguous subsequence of the inverse permutation of \(Q\).

Since we now have \(P^1=(1,2,\ldots,N)\), the vertex set of any subtree of a wonderful rooted tree can be expressed as \(\lbrace l,l+1,\ldots,r\rbrace\). For each \(l,r\), the question “Can \(\lbrace l,l+1,\ldots,r\rbrace\) be the vertex set of a subtree of a wonderful rooted tree?” can be computed in \(O(N^2M)\) time overall.

Finally, we can find the answer by doing DP with \(\mathrm{dp}[l][r]\) representing “the number of ways for subtrees with vertex set \(\lbrace l,l+1,\ldots,r\rbrace\)”. Since we need to decide the root within the subtree, the DP follows transitions like:

  • \(\mathrm{dp}[l][r]\leftarrow (\mathrm{dp}[l][i_1-1]\times \mathrm{dp}[i_1][i_2-1]\times \dots \times\mathrm{dp}[i_{\ast}][root-1])\times (\mathrm{dp}[root+1][j_1-1]\times \mathrm{dp}[j_1][j_2-1]\times \dots \times\mathrm{dp}[j_{\ast}][r])\)
    • Where vertex \(root\) is the root of the subtree, and the other vertices are decomposed into subtrees with vertex sets \(\lbrace l,i_1-1\rbrace,\lbrace i_1,i_2-1\rbrace,\ldots,\lbrace i_\ast,root-1\rbrace,\lbrace root+1,j_1-1\rbrace,\lbrace j_1,j_2-1\rbrace,\ldots,\lbrace j_\ast,r\rbrace\)

This can be optimized using interval DP and computed in \(O(N^3)\) time.

mod = 998244353

N, M = map(int, input().split())
ok = [[1] * (N + 1) for _ in range(N)]  # Whether interval [l, r) can be the vertex set of a subtree of a wonderful rooted tree
for i in range(M):
    P = list(map(lambda x: int(x) - 1, input().split()))
    if i == 0:
        inv = [0] * N
        for j, p in enumerate(P):
            inv[p] = j
    Q = [(P[inv[j]] - P[inv[0]]) % N for j in range(N)]
    pos = Q[Q.index(0) :] + Q[: Q.index(0)]
    for l in range(N):
        mn, mx = N, -1
        for r in range(l, N):
            mn = min(mn, pos[r])
            mx = max(mx, pos[r])
            ok[l][r + 1] &= r - l == mx - mn

dp1 = [[0] * (N + 1) for i in range(N + 1)]  # Number of ways interval [l, r) forms a rooted tree
dp2 = [[int(i == j) for j in range(N + 1)] for i in range(N + 1)]  # Number of ways interval [l, r) forms a rooted forest
for r in range(N + 1):
    for l in range(r - 1, 0, -1):
        if ok[l][r]:
            for m in range(l, r):
                dp1[l][r] = (dp1[l][r] + dp2[l][m] * dp2[m + 1][r]) % mod
        for m in range(l, r):
            dp2[l][r] = (dp2[l][r] + dp2[l][m] * dp1[m][r]) % mod
            
print(dp2[1][N])

posted:
last update: