結果

問題 No.2504 NOT Path Painting
ユーザー suisensuisen
提出日時 2023-02-21 08:47:46
言語 PyPy3
(7.3.15)
結果
RE  
実行時間 -
コード長 3,245 bytes
コンパイル時間 343 ms
コンパイル使用メモリ 82,068 KB
実行使用メモリ 71,984 KB
最終ジャッジ日時 2024-05-09 06:13:16
合計ジャッジ時間 4,109 ms
ジャッジサーバーID
(参考情報)
judge4 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
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 -
testcase_18 RE -
testcase_19 RE -
testcase_20 RE -
権限があれば一括ダウンロードができます

ソースコード

diff #

import functools
import operator
from collections import deque
from typing import List


P = 998244353

def inv(n):
    # return 1 / n
    return pow(n, P - 2, P)

def add(*args):
    # return sum(args)
    return sum(args) % P

def mul(*args):
    # return functools.reduce(operator.mul, args, 1)
    res = 1
    for v in args:
        res = res * v % P
    return res

def edge_num(n: int):
    return (n * (n + 1)) >> 1

def solve(n: int, g: List[List[int]]):
    m = edge_num(n)

    inv_m = inv(m)

    par_ = [0] * n
    siz_ = [1] * n
    def precalc(u: int, p: int):
        par_[u] = p
        for v in g[u]:
            if v != p:
                siz_[u] += precalc(v, u)
        return siz_[u]

    precalc(0, -1)

    def subtree_size(u: int, p: int):
        if par_[u] == p:
            return siz_[u]
        else:
            return n - siz_[p]
    
    def calc_t_1(u: int, ng1: int):
        return n - subtree_size(ng1, u)
    
    def calc_t_2(u: int, ng1: int, ng2: int):
        return n - subtree_size(ng1, u) - subtree_size(ng2, u)


    ans_f = [0] * n

    for x in range(n):
        u_x = m - sum(edge_num(subtree_size(y, x)) for y in g[x])
        ans_f[x] = mul(m, inv(m - u_x))

    ans_g = [[0] * n for _ in range(n)]

    par = [[-1] * n for _ in range(n)]

    # x, y, A, B
    dq = deque()
    for x in range(n):
        u_x = edge_num(n) - sum(edge_num(subtree_size(y, x)) for y in g[x])
        for y in g[x]:
            s_y = subtree_size(y, x)
            par[x][y] = x
            dq.append((x, y, mul(u_x - s_y * (n - s_y), ans_f[x]), 0))

    while dq:
        x, z, A, B = dq.popleft()

        par_z = par[x][z]

        s_z = subtree_size(z, par_z)

        u_z = edge_num(s_z) - sum(edge_num(subtree_size(y, z)) for y in g[z] if y != par_z)
        t_z = s_z
        
        ans_g[x][z] = add(A, mul(u_z, ans_f[z]), B)
        prev_z2, z2 = z, par_z
        while z2 != x:
            next_z2 = par[x][z2]
            t_z2 = calc_t_2(z2, prev_z2, next_z2)
            ans_g[x][z] = add(ans_g[x][z], mul(t_z, t_z2, ans_g[z][z2]))
            prev_z2, z2 = z2, next_z2
        t_x = calc_t_1(x, prev_z2)
        ans_g[x][z] = add(1, mul(ans_g[x][z], inv_m))
        ans_g[x][z] = mul(ans_g[x][z], inv(1 - mul(t_x, t_z, inv_m)))

        for y in g[z]:
            if y == par_z:
                continue

            s_y = subtree_size(y, z)
            next_t_z = t_z - s_y

            next_A = add(A, mul(u_z - s_y * (s_z - s_y), ans_f[z]))
            next_B = add(B, mul(next_t_z, t_x, ans_g[x][z]))

            prev_z2, z2 = z, par_z
            while z2 != x:
                next_z2 = par[x][z2]
                t_z2 = calc_t_2(z2, prev_z2, next_z2)
                next_B = add(next_B, mul(next_t_z, t_z2, ans_g[z][z2]))
                prev_z2, z2 = z2, next_z2

            par[x][y] = z
            dq.append((x, y, next_A, next_B))

    ans = 1
    for x in range(n):
        ans = add(ans, mul(ans_f[x], inv_m))
        for y in range(x):
            ans = add(ans, mul(ans_g[x][y], inv_m))
    print(ans)

n = int(input())
g = [[] for _ in range(n)]

for _ in range(n - 1):
    u, v = map(int, input().split())
    u -= 1
    v -= 1
    g[u].append(v)
    g[v].append(u)

solve(n, g)
0