#include #include #include using namespace std; using i64 = long long; using u64 = unsigned long long; using i32 = int; using u32 = unsigned int; #define rep(i,n) for(int i=0; i<(n); i++) ///////////////////////////////////// // Problem : https://yukicoder.me/problems/7417 // Time Complexity : O( N log^2 N ) ///////////////////////////////////// // input // // N M K // Q[1] Q[2] ... Q[N] // u[1] v[1] // u[2] v[2] // : // u[N-1] v[N-1] // struct CentroidDecomposition { int n; vector> E; vector cdep; vector cp; vector cbfs; int maxdep; CentroidDecomposition(vector> edges) { E = move(edges); n = E.size(); vector Z(n, 1); { vector P(n, -1); vector I = { 0 }; rep(i, I.size()) { int p = I[i]; for (int e : E[p]) if (P[p] != e) { P[e] = p; I.push_back(e); } } for (int i = n - 1; i >= 1; i--) Z[P[I[i]]] += Z[I[i]]; } cp.assign(n, -1); cdep.assign(n, 0); vector> I = { {0,-1} }; rep(i, I.size()) { int s = I[i].first; int par = I[i].second; while (true) { int nx = -1; for (int e : E[s]) if (Z[e] * 2 > Z[s]) nx = e; if (nx == -1) break; Z[s] -= Z[nx]; Z[nx] += Z[s]; s = nx; } cbfs.push_back(s); Z[s] = 0; if (par != -1) { cdep[s] = cdep[par] + 1; cp[s] = par; } for (int e : E[s]) if (Z[e] != 0) { I.push_back(make_pair(e, s)); } } maxdep = 0; for (int a : cdep) maxdep = max(maxdep, a); } struct BFSUnit { vector I; vector P; }; BFSUnit bfs_layer(int s, int layer) { BFSUnit res; if (cdep[s] < layer) return res; res.I.push_back(s); res.P.push_back(-1); rep(i, res.I.size()) { int p = res.I[i]; for (int e : E[p]) if (res.P[i] != e) { if (cdep[e] < layer) continue; res.I.push_back(e); res.P.push_back(p); } } return res; } }; // a^i mod M template u32 powm(u32 a,u64 i) { if(i == 0) return 1; u32 r = powm((u64)a*a%MOD,i/2); if(i&1) r = (u64)r*a%MOD; return r; } template void NTT(vector& A){ int N = 1; while (N < A.size()) N *= 2; static vector exp_i_revbit_diff = { (u32)powm(g, (MOD - 1) >> 2) }; for(int i=exp_i_revbit_diff.size(); (1<<(i+1))(g, (MOD - 1) / 2 + ((MOD - 1) >> (i+2)) * 3); exp_i_revbit_diff.push_back(diffdiff); } for (int i = 1; i < N; i <<= 1) { u64 q = 1; int maxk = N / i / 2; for (int j = 0; j < i; j++) { int off = j * maxk * 2; for (int k = off; k < off + maxk; k++) { u32 l = A[k]; u32 r = A[k + maxk] * q % MOD; A[k] = min(l + r - MOD, l + r); A[k + maxk] = min(l - r, l + MOD - r); } if(j+1 != i) for(int d=0; ; d++) if(!(j&(1<> 1; k > (i ^= k); k >>= 1); } } const u64 MOD = 998244353; const u64 NTTzeta = 3; int N; vector Q; vector> E; u64 k0; vector inv_mod; vector C; vector> nttC; vector inv_ntt_size; vector ans; vector bfsbuf_dist; void get_bfsbuf_dist(CentroidDecomposition::BFSUnit tree){ bfsbuf_dist[tree.I.front()] = 0; for(int i=1; i sigma(const vector& B){ int n = B.size() + 2; int Z = 1, d = 0; while(Z < n){ Z *= 2; d++; } vector revB(Z*2, 0); rep(i, B.size()) revB[Z-i] = B[i]; NTT(revB); rep(i, Z*2) revB[i] = (u64)revB[i] * nttC[d+1][i] % MOD; NTT(revB); reverse(revB.begin() + 1, revB.end()); rep(i, n) revB[i] = (u64)revB[i+Z] * inv_ntt_size[d+1] % MOD; revB.resize(n); return revB; } vector sigma_tree(const CentroidDecomposition::BFSUnit& tree){ vector dist_freq(tree.I.size(), 0); get_bfsbuf_dist(tree); for(int p : tree.I){ dist_freq[bfsbuf_dist[p]] += Q[p]; if(dist_freq[bfsbuf_dist[p]] >= MOD) dist_freq[bfsbuf_dist[p]] -= MOD; } return sigma(dist_freq); } int main() { cin >> N; Q.resize(N); rep(i,N) cin >> Q[i]; E.resize(N); rep(i,N-1){ int u,v; cin >> u >> v; u--; v--; E[u].push_back(v); E[v].push_back(u); } int max_ntt_size_log = 0; while((1 << max_ntt_size_log) < N + 6) max_ntt_size_log++; max_ntt_size_log++; int max_ntt_size = 1 << max_ntt_size_log; k0 = 1; for(int i=1; i<=N; i++) k0 = k0 * i % MOD; k0 = k0 * k0 % MOD; inv_mod.assign(max_ntt_size+1, 1); for(int i=2; i<=max_ntt_size; i++) inv_mod[i] = MOD - MOD / i * inv_mod[MOD % i] % MOD; C.resize(max_ntt_size); for(int i=0; i(nttC[d]); inv_ntt_size[d] = powm(1< sigma_s = sigma_tree(bfs_s); for(int nx : E[s]) if(centroid_decomposition.cdep[nx] > dep_s){ CentroidDecomposition::BFSUnit bfs_nx = centroid_decomposition.bfs_layer(nx, dep_s+1); vector sigma_nx = sigma_tree(bfs_nx); for(int p : bfs_nx.I){ int d = bfsbuf_dist[p] + 1; ans[p] = (ans[p] + (sigma_s[d] + MOD - sigma_nx[d+1])) % MOD; } } ans[s] = (ans[s] + sigma_s[0]) % MOD; } rep(p,N) cout << ans[p] << "\n"; return 0; }