結果

問題 No.1667 Forest
ユーザー 草苺奶昔草苺奶昔
提出日時 2023-03-14 17:02:51
言語 PyPy3
(7.3.15)
結果
RE  
実行時間 -
コード長 1,554 bytes
コンパイル時間 435 ms
コンパイル使用メモリ 81,820 KB
実行使用メモリ 65,924 KB
最終ジャッジ日時 2023-10-18 11:54:08
合計ジャッジ時間 3,096 ms
ジャッジサーバーID
(参考情報)
judge14 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 RE -
testcase_01 RE -
testcase_02 RE -
testcase_03 RE -
testcase_04 RE -
testcase_05 RE -
testcase_06 RE -
testcase_07 RE -
testcase_08 RE -
testcase_09 RE -
testcase_10 RE -
testcase_11 RE -
testcase_12 RE -
testcase_13 RE -
testcase_14 RE -
testcase_15 RE -
testcase_16 RE -
testcase_17 RE -
権限があれば一括ダウンロードができます

ソースコード

diff #

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