题目链接:​​传送门​

求树上最长的一条路径使得路径上点权的gcd>1

既然要使gcd>1那么这些点一定有公共的一个因子
我们可以枚举这个因子找树上符合条件的最长的链
嗯对这是一种做法应该可以过
再看一个树形dp的做法
我们需要先预处理出每个点权值的因子CF1101D GCD Counting_树形dp
CF1101D GCD Counting_数论_02表示路径中包含CF1101D GCD Counting_gcd_03这一点且公共因子为CF1101D GCD Counting_gcd_04的最长路径
每次递归回来需要枚举因子更新答案
因子相同才可以通过它的子节点更新

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define
#define

using namespace std;
typedef long long ll;
struct node {
int next, to;
}e[A];
int head[A], num;
void add(int fr, int to) {
e[++num].next = head[fr];
e[num].to = to;
head[fr] = num;
}
int n, w[A], a, b, ans = 1, pri;
vector<int> p[A], f[A];
void divide(int x, int id) {
for (int i = 2; i * i <= x; i++)
if (x % i == 0) {
p[id].push_back(i); f[id].push_back(1);
while (x % i == 0) x /= i;
}
if (x > 1) p[id].push_back(x), f[id].push_back(1);
}
void dfs(int fr, int fa) {
for (int i = head[fr]; i; i = e[i].next) {
int ca = e[i].to;
if (ca == fa) continue;
dfs(ca, fr);
for (int j = 0; j < p[fr].size(); j++)
for (int k = 0; k < p[ca].size(); k++) {
if (p[fr][j] != p[ca][k]) continue;
ans = max(ans, f[fr][j] + f[ca][k]); //连接两条路径
f[fr][j] = max(f[fr][j], f[ca][k] + 1);
}
}
}

int main(int argc, char const *argv[]) {
cin >> n;
for (int i = 1; i <= n; i++){
cin >> w[i], divide(w[i], i);
if (w[i] != 1) pri = 1;
}
if (!pri) return puts("0"), 0;
for (int i = 2; i <= n; i++) cin >> a >> b, add(a, b), add(b, a);
dfs(1, 1); cout << ans << endl;
}