题解
用sqrt(a)/log a的时间分解质因数。
枚举一个质因数x,所有x的倍数节点打标记。
对于每一个被标记的联通块求直径。
#include<cstdio>
#include<algorithm>
#include<map>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=100000+10,maxd=32000+10;
map<int,int> id;
int h[maxn],go[maxn*2],nxt[maxn*2],a[maxn],b[maxn*11],f[maxn];
int h2[maxn*11],g2[maxn*11],n2[maxn*11];
int pri[maxd];
bool bz[maxd],pd[maxn],vis[maxn];
int i,j,k,l,t,n,m,tot,top,num,cnt,ans,mx,now;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void prepare(){
fo(i,2,maxd-10){
if (!bz[i]) pri[++top]=i;
fo(j,1,top){
if ((ll)i*pri[j]>maxd-10) break;
bz[i*pri[j]]=1;
if (i%pri[j]==0) break;
}
}
}
void add(int x,int y){
go[++tot]=y;
nxt[tot]=h[x];
h[x]=tot;
}
void add2(int x,int y){
g2[++cnt]=y;
n2[cnt]=h2[x];
h2[x]=cnt;
}
void dfs(int x,int y,int z){
vis[x]=1;
if (z>now) mx=x,now=z;
int t=h[x];
while (t){
if (go[t]!=y&&pd[go[t]]) dfs(go[t],x,z+1);
t=nxt[t];
}
}
int main(){
prepare();
n=read();
fo(i,1,n-1){
j=read();k=read();
add(j,k);add(k,j);
}
tot=0;
fo(i,1,n){
a[i]=read();
k=a[i];
fo(j,1,top){
if ((ll)pri[j]*pri[j]>k) break;
if (k%pri[j]==0){
if (id[pri[j]]==0) id[pri[j]]=++tot,b[++num]=pri[j];
add2(id[pri[j]],i);
while (k%pri[j]==0) k/=pri[j];
}
}
if (k>1){
if (id[k]==0) id[k]=++tot,b[++num]=k;
add2(id[k],i);
}
}
fo(i,1,num){
t=h2[id[b[i]]];
while (t){
pd[g2[t]]=1;
t=n2[t];
}
t=h2[id[b[i]]];
while (t){
if (!vis[g2[t]]){
mx=0;now=-1;
dfs(g2[t],0,0);
now=-1;
dfs(mx,0,0);
ans=max(ans,now);
}
t=n2[t];
}
t=h2[id[b[i]]];
while (t){
vis[g2[t]]=0;
t=n2[t];
}
t=h2[id[b[i]]];
while (t){
pd[g2[t]]=0;
t=n2[t];
}
}
printf("%d\n",ans+1);
}

345





