• Codeforces Round #588 (Div. 2) E. Kamil and Making a Stream(dfs)


    题意:

    给一棵 \(n\) 个节点的树,定义 \(f(u,v)\),其中 \(u\)\(v\) 的祖先,\(f(u,v)\) 等于 \(u\) \(\rightarrow\) \(v\) 路径上所有点权值的 \(gcd\)。现求一棵树上所有的 \(f(u,v)\) 之和。

    分析:

    简单的 \(dfs\),难点可能在于不好估计复杂度。一棵树上所有的 \(f(u,v)\) \((u!=v)\) 权值数不会超过 \(log_2(1e12)\) 种,暴力即可。
    我们用一个 \(map\) 记录每个点的祖先到其的 \(gcd\) 和到这个点的 \(gcd\) 出现的次数,那么就可以计算贡献了。因为 \(f(u,v)\) 权值数不会超过 \(log_2(1e12)\) 种,所以对每个节点暴力向其孩子求贡献的总复杂度是 \(O(nlog_2(1e12))\)

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    #define pb push_back
    
    const int N = 1e5 + 5;
    const LL mod = 1e9 + 7;
    
    int n, u, v;
    LL ans, w[N];
    vector<int> g[N];
    unordered_map<LL, int> maps[N];
    
    void add(int u, LL w, int p) {
    	ans = (ans + 1LL * p * w % mod) % mod;
    	maps[u][w] += p;
    }
    
    void dfs(int u, int f) {
    	add(u, w[u], 1);
    	for (auto it : g[u]) {
    		if (it == f) continue;
    		for (auto it1 : maps[u]) add(it, __gcd(w[it], it1.first), it1.second);
    		dfs(it, u);
    	}
    }
    
    int main() { 
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++) scanf("%lld", w + i);
    	for (int i = 1; i <= n - 1; i++) {
    		scanf("%d %d", &u, &v);
    		g[u].pb(v), g[v].pb(u);
    	}
    	dfs(1, -1);
    	printf("%lld\n", ans);
    	return 0;
    }
    
  • 相关阅读:
    pandas 和 matplotlib 的设置
    Django图(菜鸟教程)
    使用 pyperclip 实现复制粘贴
    Pycharm 使用 doctest 进行判断程序是否运行正常
    jieba 运行结果不显示 Building prefix dict from the default dictionary ...
    浮点数以 .0 结尾如何转换为整数
    IOS时间转时间戳出现Invalid Date的问题
    PHP小技巧
    CSS小技巧
    树状数组
  • 原文地址:https://www.cnblogs.com/ChaseNo1/p/11588231.html
Copyright © 2020-2023  润新知