枚举每一个质数,权值是这个质数的倍数的节点设为1,否则为0,那么最长长链的长度就是点权为1的点构成的最长的链。
当然不用枚举所以质数,因为每个数最多有log个不同的质因数,所以只要把所有点权质因数分解,枚举出现的质数就可以了。
枚举质数后dfs,复杂度是nlogn的,因为每个点有log个不同的质因数,也就是说最多枚举到log个质数要dfs这个节点,所以复杂度是对的
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#define pb push_back
using namespace std;
const int N=100010;
int n,u,v,cnt,L,ans;
int p[N],vis[N],a[N],pnt;
map<int,vector<int> > M;
vector<int> e[N];
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void rea(int &x){
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
inline void Pre(int n){
for(int i=2;i<=n;i++){
if(!p[i]) p[++pnt]=i;
for(int j=1;j<=pnt&&1LL*i*p[j]<=n;j++){
p[p[j]*i]=1;
if(i%p[j]==0) break;
}
}
}
void dfs(int u,int f,int p){
L++; vis[u]=p;
for(int v : e[u])
if(v!=f&&a[v]%p==0) dfs(v,u,p);
}
int main(){
rea(n); Pre(100000);
for(int i=1;i<n;i++)
rea(u),rea(v),e[u].pb(v),e[v].pb(u);
for(int i=1;i<=n;i++){
int x; rea(x); a[i]=x;
for(int j=1;j<=pnt&&1LL*p[j]*p[j]<=x;j++)
if(x%p[j]==0){
while(x%p[j]==0) x/=p[j];
M[p[j]].pb(i);
if(x==1) break;
}
if(x!=1) M[x].pb(i);
}
for(auto s : M){
int p=s.first;
vector<int> v=s.second;
for(int u : v)
if(vis[u]!=p){
L=0; dfs(u,0,p);
ans=max(ans,L);
}
}
printf("%d\n",ans); return 0;
}