結果

問題 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
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 974 ms
136,448 KB
testcase_01 AC 1,025 ms
136,832 KB
testcase_02 AC 967 ms
136,832 KB
testcase_03 AC 429 ms
136,064 KB
testcase_04 AC 962 ms
136,576 KB
testcase_05 AC 743 ms
136,320 KB
testcase_06 AC 615 ms
136,576 KB
testcase_07 AC 543 ms
136,448 KB
testcase_08 AC 483 ms
135,936 KB
testcase_09 AC 456 ms
136,064 KB
testcase_10 AC 442 ms
135,424 KB
testcase_11 AC 431 ms
136,052 KB
testcase_12 AC 409 ms
129,792 KB
testcase_13 AC 407 ms
129,920 KB
testcase_14 AC 412 ms
129,664 KB
testcase_15 AC 410 ms
129,536 KB
testcase_16 AC 403 ms
129,792 KB
testcase_17 AC 411 ms
130,048 KB
権限があれば一括ダウンロードができます

ソースコード

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