結果

問題 No.1667 Forest
ユーザー 草苺奶昔
提出日時 2023-03-14 17:03:03
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 1,025 ms / 3,000 ms
コード長 1,968 bytes
コンパイル時間 203 ms
コンパイル使用メモリ 82,576 KB
実行使用メモリ 136,832 KB
最終ジャッジ日時 2024-09-18 08:17:10
合計ジャッジ時間 12,409 ms
ジャッジサーバーID
(参考情報)
judge4 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 15
権限があれば一括ダウンロードができます

ソースコード

diff #

from typing import List


MOD = int(1e9 + 7)
fac = [1]
ifac = [1]
for i in range(1, int(4e5) + 10):
    fac.append((fac[-1] * i) % MOD)
    ifac.append((ifac[-1] * pow(i, MOD - 2, MOD)) % MOD)


def count_tree_by_root_degree(n: int, root_degree: int) -> int:
    d = root_degree
    if d <= 0 or d >= n:
        return 0
    d -= 1
    return fac[n - 2] * ifac[d] * ifac[n - 2 - d] * pow(n - 1, n - 2 - d, MOD)


if __name__ == "__main__":
    # https://yukicoder.me/problems/no/1667
    # !对m = 0, 1, 2, ..., n - 1, 求n个顶点m条边的森林的个数(顶点有区别,边没有区别)
    # n<=300 MOD为素数
    # 1.cayley定理(凯莱定理):n个有标号顶点的树的个数为n^(n-2)
    # 2.dp[i][j]表示i个顶点j条边的森林(无环图)的个数
    # 每次dp转移考虑剩下的顶点中最小的
    # !- dp[i+1][j] += dp[i][j] (加入一个新的顶点,不与任何边相连)
    # !- dp[i+k][j+k-1] += dp[i][j] * C(n-i-1,k-1) * k^(k-2) (加入一个k个顶点的树)
    def countForest(n: int, MOD: int) -> List[int]:
        cayley = [0] * (n + 1)
        cayley[1] = 1
        for i in range(2, n + 1):
            cayley[i] = pow(i, i - 2, MOD)

        dp = [[0] * (n + 1) for _ in range(n + 1)]
        dp[0][0] = 1
        for i in range(n):
            for j in range(i + 1):
                for k in range(1, n + 1):
                    if i + k <= n:
                        dp[i + k][j + k - 1] += dp[i][j] * C(n - i - 1, k - 1) % MOD * cayley[k]
                        dp[i + k][j + k - 1] %= MOD
        return dp[n][:-1]

    n, MOD = map(int, input().split())
    fac = [1]
    ifac = [1]
    for i in range(1, int(1e3) + 10):
        fac.append((fac[-1] * i) % MOD)
        ifac.append((ifac[-1] * pow(i, MOD - 2, MOD)) % MOD)

    def C(n: int, k: int) -> int:
        if n < 0 or k < 0 or n < k:
            return 0
        return ((fac[n] * ifac[k]) % MOD * ifac[n - k]) % MOD

    print(*countForest(n, MOD), sep="\n")
0