cf1210 C. Kamil and Making a Stream


题意:

一棵有点权的树,定义路径的值为路径上所有点取 gcd。

只考虑祖先-后代路径(即路上每个点的深度不同,不考虑那种v形的),求所有路径的值之和,取模。

点权范围 1e12

思路:

一条链上,从上往下取一路取 gcd,最多会产生 \(log(链头的值)\le log(1e12)<40\) 个不同的值

map 暴力记录父亲传下来的所有数的集合

注意取模会影响 gcd,别取模

void dfs(int u, int fa, map pre) {
    pre[a[u]]++;
    map now;
    for(auto &[x, cnt] : pre) {
        ll y = __gcd(x, a[u]);
        (ans += cnt * y) %= mod;
        now[y] += cnt;
    }

    for(int v : G[u]) if(v != fa)
        dfs(v, u, now);
}

signed main() {
    iofast;
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i < n; i++) {
        int u, v; cin >> u >> v;
        G[u].pb(v), G[v].pb(u);
    }
    dfs(1, 0, map());
    cout << ans;
}