#include namespace { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #include #pragma GCC diagnostic pop using namespace std; using namespace atcoder; #define rep(i,n)for (int i = 0; i < int(n); ++i) #define rrep(i,n)for (int i = int(n)-1; i >= 0; --i) #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() template void chmax(T& a, const T& b) { a = max(a, b); } template void chmin(T& a, const T& b) { a = min(a, b); } using ll = long long; using P = pair; using VI = vector; using VVI = vector; using VL = vector; using VVL = vector; using mint = modint998244353; template struct array_set { int state[element_size]; // -1 if not in set else index in elems int elems[element_size]; int size = 0; array_set() { memset(state, -1, sizeof(int) * element_size); } void insert(int x) { if (state[x] == -1) { state[x] = size; elems[size] = x; size++; } } bool contains(int x) { return state[x] != -1; } int* begin() { return elems; } int* end() { return elems + size; } void clear() { while(size) state[elems[--size]] = -1; } void erase(int x) { // not tested int idx = state[x]; if (idx != -1) { state[x] = -1; size--; if (idx != size) { int y = elems[size]; state[y] = idx; elems[idx] = y; } } } }; template struct array_unordered_map { int state[element_size]; // -1 if not in set else index in elems pair elems[element_size]; int size = 0; array_unordered_map() { memset(state, -1, sizeof(int) * element_size); } bool contains(int x) { return state[x] != -1; } pair* begin() { return elems; } pair* end() { return elems + size; } void clear() { while(size) state[elems[--size].first] = -1; } void erase(int x) { // not tested int idx = state[x]; if (idx != -1) { state[x] = -1; size--; if (idx != size) { int y = elems[size].first; state[y] = idx; elems[idx] = move(elems[size]); } } } T& operator[](int x) { if (state[x] == -1) { state[x] = size; elems[size].first = x; elems[size].second = T(); size++; } return elems[state[x]].second; } }; constexpr int FACT_SIZE = 1000000; mint Fact[FACT_SIZE + 1]; mint iFact[FACT_SIZE + 1]; const auto fact_init = [] { Fact[0] = mint::raw(1); for(int i = 1; i <= FACT_SIZE; ++i) { Fact[i] = Fact[i-1] * i; } iFact[FACT_SIZE] = Fact[FACT_SIZE].inv(); for(int i = FACT_SIZE; i; --i) { iFact[i-1] = iFact[i] * i; } return false; }(); mint comb(int n, int k) { if (k == 0) return mint::raw(1); assert(n >= 0 && k >= 0); if (k > n) return mint::raw(0); return Fact[n] * iFact[n - k] * iFact[k]; } mint icomb(int n, int k) { return iFact[n] * Fact[n - k] * Fact[k]; } mint fact(int n) {return Fact[n];} mint perm(int n, int k) { assert(0 <= n); return Fact[n] * iFact[n - k]; } mint inv2[FACT_SIZE + 1]; } int main() { ios::sync_with_stdio(false); cin.tie(0); for(int i = 1; i <= FACT_SIZE; i++) { mint x = iFact[i] * Fact[i - 1]; inv2[i] = x * x; } int n; cin >> n; vector q(n); rep(i, n) { int x; cin >> x; q[i] = x; } VVI to(n); rep(_, n - 1) { int u, v; cin >> u >> v; u--, v--; to[u].emplace_back(v); to[v].emplace_back(u); } VI sz(n), par(n); vector ans = q; auto dfs = [&](auto&& self, int u) -> void { auto get_total_size = [&](auto&& self, int u) -> int { static array_set<200000> visited; static VI q; visited.clear(); q.emplace_back(u); visited.insert(u); while(!q.empty()) { int u = q.back(); q.pop_back(); for(int v: to[u]) if (!visited.contains(v)) { q.emplace_back(v); visited.insert(v); } } return visited.size; }; int sz_tot = get_total_size(get_total_size, u); if (sz_tot == 1) { return; } else if (sz_tot == 2) { int v = to[u][0]; ans[u] += inv2[2] * q[v]; ans[v] += inv2[2] * q[u]; return; } auto get_centroid = [&](auto&& self, int u, int p=-1) -> int { sz[u] = 1; par[u] = p; int res = -1; for(int v: to[u]) if (v != p) { int r = self(self, v, u); if (r >= 0) res = r; sz[u] += sz[v]; } if (res == -1 && sz_tot - sz[u] <= sz_tot / 2) { bool ok = true; for(int v: to[u]) if (v != p) { if (sz[v] > sz_tot / 2) { ok = false; break; } } if (ok) res = u; } return res; }; int c = get_centroid(get_centroid, u); for(int v : to[c]) if (v == par[c]) { sz[v] = sz_tot - sz[c]; } // 1/3, 2/3 VI e1, e2; int x = -1; for(int v : to[c]) if (sz[v] >= sz_tot / 3) { x = v; break; } if (x != -1) { e1.emplace_back(x); for(int v : to[c]) if (v != x) { e2.emplace_back(v); } } else { int now = 0; for(int v: to[c]) { if (now + sz[v] <= sz_tot / 2) { e1.emplace_back(v); now += sz[v]; } else { e2.emplace_back(v); } } } to[c].clear(); static array_unordered_map mp[2]; int depth_mx[2] = {}; auto dfs = [&](int u, auto& mp) { mp.clear(); static VI st; mp[u] = 0; st.emplace_back(u); while(!st.empty()) { int u = st.back(); st.pop_back(); for(int v: to[u]) if (!mp.contains(v)) { mp[v] = mp[u] + 1; st.emplace_back(v); } } }; rep(z, 2) { swap(to[c], e1); dfs(c, mp[z]); for(auto [_, d] : mp[z]) chmax(depth_mx[z], d); swap(to[c], e1); swap(e1, e2); } int len = depth_mx[0] + depth_mx[1] - 1; vector g(len); rep(i, len) g[i] = inv2[i + 3]; rep(z, 2) { vector f(depth_mx[z]); for(auto [u, d] : mp[z]) if (d) { f[depth_mx[z] - d] += q[u]; } auto h = convolution(f, g); for(auto [u, d] : mp[1 - z]) if (d) { ans[u] += h[depth_mx[z] - 1 + (d - 1)]; } } rep(_, 2) { to[c] = move(e1); self(self, c); swap(e1, e2); } }; dfs(dfs, 0); mint k0 = fact(n) * fact(n); rep(i, n) cout << (k0 * ans[i]).val() << '\n'; }