题意:给你一棵树,根节点是1,每个节点都有一个权值,现在要求出每个节点的结果,结果的定义为从根节点到该节
点(包含)路径上所有点的值的gcd,求解每个点时可以把路径上某一个点的值变为0。每个节点的结果独立计算。
思路:可以直接进行dfs,每个节点用set分别保存它到根节点不取每一个点的gcd,比如路径为1 - 2 - 3 - 4,4号节点
保存的set是gcd(a[1], a[2], a[3]), gcd(a[1], a[2], a[4]), gcd(a[1], a[3], a[4]), gcd(a[2], a[3], a[4]), gcd(a[1], a[2], a[3],
a[4]).
这样对于求解每个节点的set我们可以从它的父节点转移过来。
因为约数的值不会很多,很多进行多次gcd后都变成了1.所以并不会T
代码:
#include<bits/stdc++.h> using namespace std; const int maxn = 2e5+5; vector<int>g[maxn]; set<int> s[maxn]; set<int>::iterator it; int n, a[maxn]; void dfs(int u, int pre, int gcd) { for(it = s[pre].begin(); it != s[pre].end(); it++) s[u].insert(__gcd(*it, a[u])); s[u].insert(gcd); s[u].insert(__gcd(gcd, a[u])); for(int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if(v == pre) continue; dfs(v, u, __gcd(gcd, a[u])); } } int main(void) { while(cin >> n) { for(int i = 0; i < maxn; i++) g[i].clear(), s[i].clear(); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); g[u].push_back(v); g[v].push_back(u); } dfs(1, 0, 0); for(int i = 1; i <= n; i++) printf("%d%c", *(s[i].rbegin()), i==n ? '\n' : ' '); } return 0; }