// by gemini 2.5 pro #include #include #include #include #include // using namespace std; を使う代わりに、必要なものだけを宣言 using std::cin; using std::cout; using std::map; using std::max; using std::swap; using std::vector; using ll = long long; // 問題で指定された剰余 const int MOD = 998244353; // a_i の最大値 + 5 const int MAX_A = 1000005; // 高速な素因数分解のための前処理用配列 vector min_prime; /** * @brief エラトステネスの篩を用いて、nまでの各数の最小素因数を求める * @param n 上限値 */ void sieve(int n) { min_prime.assign(n + 1, 0); for (int i = 2; i <= n; ++i) { if (min_prime[i] == 0) { // iが素数 min_prime[i] = i; for (ll j = (ll)i * i; j <= n; j += i) { if (min_prime[j] == 0) { min_prime[j] = i; } } } } } /** * @brief 前処理したテーブルを使い、数nを高速に素因数分解する * @param n 素因数分解する数 * @return map<素因数, 指数> */ map factorize(int n) { map factors; if (n <= 1) return factors; while (n > 1) { factors[min_prime[n]]++; n /= min_prime[n]; } return factors; } /** * @brief 繰り返し二乗法で base^exp % MOD を計算する */ ll power(ll base, ll exp) { ll res = 1; base %= MOD; while (exp > 0) { if (exp % 2 == 1) res = (res * base) % MOD; base = (base * base) % MOD; exp /= 2; } return res; } int N; vector A; vector> adj; vector> factors; vector ans; /** * @brief DFSで部分木のLCMを計算する * @param u 現在の頂点 * @param p 親の頂点 * @return 頂点uの部分木のLCMの素因数分解マップ */ map dfs(int u, int p) { // まず自分自身の重みの素因数でマップを初期化 map res_map = factors[u]; for (int v : adj[u]) { if (v == p) continue; // 子vの部分木の素因数マップを取得 map child_map = dfs(v, u); // Small-to-Large Merging: 常に大きいマップに小さいマップをマージする if (child_map.size() > res_map.size()) { swap(child_map, res_map); } // マージ処理(各素数の指数の最大値をとる) for (auto const& [prime, exp] : child_map) { res_map[prime] = max(res_map[prime], exp); } } // 計算結果の素因数マップからLCMの値を復元 ll current_lcm = 1; for (auto const& [prime, exp] : res_map) { current_lcm = (current_lcm * power(prime, exp)) % MOD; } ans[u] = current_lcm; return res_map; } int main() { // 高速な入出力 std::ios_base::sync_with_stdio(false); cin.tie(NULL); // 入力 cin >> N; A.resize(N + 1); factors.resize(N + 1); adj.resize(N + 1); ans.resize(N + 1); for (int i = 1; i <= N; ++i) { cin >> A[i]; } for (int i = 0; i < N - 1; ++i) { int u, v; cin >> u >> v; adj[u].push_back(v); adj[v].push_back(u); } // --- 前処理 --- // 1. エラトステネスの篩 sieve(MAX_A - 1); // 2. 全ての重みを素因数分解 for (int i = 1; i <= N; ++i) { factors[i] = factorize(A[i]); } // --- 計算 --- // 問題文より根は1で固定。親は存在しない0とする。 dfs(1, 0); // --- 出力 --- for (int i = 1; i <= N; ++i) { cout << ans[i] << "\n"; } return 0; }