zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    第三章 系统总线
    人工神经网络及其应用
    专家系统
    遗传算法
    搜索算法策略
    js判断有无属性及新添属性
    vue 文件插件 Vetur 设置说明官网
    vue 获得当前无素并做相应处理
    VUE style 绑定
    vue入门基础知识点测试
  • 原文地址:https://www.cnblogs.com/ChaseNo1/p/11588231.html
Copyright © 2011-2022 走看看