結果

問題 No.3250 最小公倍数
ユーザー shinchan
提出日時 2025-08-30 02:20:31
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 1,542 ms / 2,000 ms
コード長 7,607 bytes
コンパイル時間 2,831 ms
コンパイル使用メモリ 210,916 KB
実行使用メモリ 129,628 KB
最終ジャッジ日時 2025-08-30 02:20:57
合計ジャッジ時間 20,078 ms
ジャッジサーバーID
(参考情報)
judge2 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 1
other AC * 21
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb emplace_back
#define rep(i, n) for(int i=0;i<(n);i++)
#define foa(e, v) for(auto& e : v)
#define dout(a) cout<<fixed<<setprecision(10)<<a<<'\n';
#define Cout(a) cout<<a<<'\n';

using ll = long long;
using ld = long double;
using Int = __int128;
template <class T> using pqr = priority_queue<T, vector<T>, greater<T>>;

template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) {
    bool compare = a < b;
    if(compare) a = b;
    return compare;
}
template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) {
    bool compare = a > b;
    if(compare) a = b;
    return compare;
}
template <typename T> inline T back(std::set<T> &s) {
    return *s.rbegin();
}
template <typename T> inline T back(std::multiset<T> &s) {
    return *s.rbegin();
}
template <typename T> inline T pop_back(std::set<T> &s) {
    auto it = prev(s.end());
    T val = *it;
    s.erase(it); 
    return val;
}
template <typename T> inline T pop_back(std::multiset<T> &s) {
    auto it = prev(s.end());
    T val = *it;
    s.erase(it); 
    return val;
}

const int dy[8] = {-1, 0, 0, 1, 1, -1, 1, -1};
const int dx[8] = {0, -1, 1, 0, -1, -1, 1, 1};

const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (3LL << 59);
const int inf = 1 << 30;
const char br = '\n';

template<int MOD> struct Modint {
    long long val;
    constexpr Modint(long long v = 0) noexcept : val(v % MOD) { if (val < 0) val += MOD; }
    constexpr int mod() const { return MOD; }
    constexpr long long value() const { return val; }
    constexpr Modint operator - () const noexcept { return val ? MOD - val : 0; }
    constexpr Modint operator + (const Modint& r) const noexcept { return Modint(*this) += r; }
    constexpr Modint operator - (const Modint& r) const noexcept { return Modint(*this) -= r; }
    constexpr Modint operator * (const Modint& r) const noexcept { return Modint(*this) *= r; }
    constexpr Modint operator / (const Modint& r) const noexcept { return Modint(*this) /= r; }
    constexpr Modint& operator += (const Modint& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Modint& operator -= (const Modint& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Modint& operator *= (const Modint& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Modint& operator /= (const Modint& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Modint& r) const noexcept { return this->val == r.val; }
    constexpr bool operator != (const Modint& r) const noexcept { return this->val != r.val; }
    friend constexpr istream& operator >> (istream& is, Modint<MOD>& x) noexcept {
        is >> x.val;
        x.val %= MOD;
        if (x.val < 0) x.val += MOD;
        return is;
    }
    friend constexpr ostream& operator << (ostream& os, const Modint<MOD>& x) noexcept {
        return os << x.val;
    }
    constexpr Modint<MOD> pow(long long n) noexcept {
        if (n == 0) return 1;
        if (n < 0) return this->pow(-n).inv();
        Modint<MOD> ret = pow(n >> 1);
        ret *= ret;
        if (n & 1) ret *= *this;
        return ret;
    }
    constexpr Modint<MOD> inv() const noexcept {
        long long a = this->val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        return Modint<MOD>(u);
    }
};

const int MOD = MOD998;
using mint = Modint<MOD>;

struct Doubling {
private:
    static constexpr int max_bit = 20;
    std::vector<std::array<int, max_bit>> nx;
    std::vector<int> dis;
public:
    Doubling(std::vector<std::vector<int>> v, int s = 0) noexcept { 
        int n = v.size();
        dis.resize(n, 1 << 30);
        nx.resize(n);
        dis[s] = 0;
        auto dfs = [&] (auto dfs, int now, int p = -1) -> void {
            nx[now][0] = p;
            for(int to : v[now]) {
                if(to == p) continue;
                dis[to] = dis[now] + 1;
                dfs(dfs, to, now);
            }
        };
        dfs(dfs, s);
        for(int j = 0; j < max_bit - 1; j ++) for(int i = 0; i < n; i ++) {
            if(nx[i][j] != -1) nx[i][j + 1] = nx[nx[i][j]][j];
            else nx[i][j + 1] = -1;
        }
    }
    Doubling(std::vector<int> nx_) noexcept {
        int n = nx_.size();
        nx.resize(n);
        for(int i = 0; i < n; i ++) nx[i][0] = nx_[i];
        for(int j = 0; j < max_bit - 1; j ++) for(int i = 0; i < n; i ++) {
            if(nx[i][j] != -1) nx[i][j + 1] = nx[nx[i][j]][j];
            else nx[i][j + 1] = -1;
        }
    }

    // nowのm個先 (LCAではm個親)
    int par(int now, long long m) {
        while(m) {
            if(now == -1) return -1;
            int t = __builtin_ctzll(m);
            now = nx[now][t];
            m ^= 1LL << t;
        }
        return now;
    }

    // Lowest Common Ancestor
    int lca(int a, int b) {
        if(dis[a] != dis[b]) {
            if(dis[a] > dis[b]) swap(a, b);
            b = par(b, dis[b] - dis[a]);
        }
        if(a == b) return a;
        for(int i = __lg(dis[a]); i >= 0; i --) {
            if(dis[a] < (1 << i)) continue;
            if(nx[a][i] != nx[b][i]) a = nx[a][i], b = nx[b][i];
        }
        return nx[a][0];
    }

    // distance between a and b
    int dist(int a, int b){return dis[a] + dis[b] - (dis[lca(a, b)] << 1);}
};


int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    vector<ll> a(n);
    rep(i, n) cin >> a[i];
    vector<vector<int>> v(n);
    rep(i, n - 1) {
        int x, y; cin >> x >> y;
        x --; y --;
        v[x].pb(y);
        v[y].pb(x);
    }
    vector<mint> imos(n, 1);
    int N = 1000000;
    vector<int> pri(N + 1, -1);
    for(int i = 2; i <= N; i ++) {
        if(pri[i] != -1) continue;
        for(int j = i; j <= N; j += i) {
            if(pri[j] == -1) pri[j] = i;
        }
    }
    Doubling d(v);
    vector<vector<int>> vec(N);
    vector<int> pr(N);
    auto dfs = [&](auto dfs, int now, int p) -> void {
        vector<int> x;
        while(a[now] > 1) {
            x.pb(pri[a[now]]);
            a[now] /= pri[a[now]];
        }
        int sum = 1;
        int pp = -1;
        foa(e, x) {
            if(e == pp) {
                sum *= e;
            } else {
                sum = e;
            }
            vec[sum].pb(now);
            pr[sum] = e;
            pp = e;
        }
        foa(e, v[now]) {
            if(e == p) continue;
            dfs(dfs, e, now);
        }
    };
    dfs(dfs, 0, -1);
    vector<mint> inv(N + 1);
    for(int i = 1; i <= N; i ++) inv[i] = mint(i).inv();
    for(int i = 2; i <= N; i ++) {
        int pp = -1;
        foa(e, vec[i]) {
            imos[e] *= pr[i];
            if(pp != -1) {
                int lca = d.lca(pp, e);
                imos[lca] *= inv[pr[i]];
            }
            pp = e;
        }
    }
    auto f = [&](auto &&f, int now, int p) -> void {
        foa(e, v[now]) {
            if(e == p) continue;
            f(f, e, now);
            imos[now] *= imos[e];
        }
    };
    f(f, 0, -1);
    foa(e, imos) Cout(e);
    return 0;
}
0