首先线性筛求出2到1000000中每个数的质因数分解。
然后进行DFS,并用一个数组保存最近一次出现质因数i的位置。
对于每个节点,遍历它的值所有的质因数,并求出当前所有质因数最近出现位置的节点中,深度的最大值,将这个节点作为结果。
然后,对于节点的值的每个质因数,更新这个数组的值,将这个节点作为最近一次出现的位置。
回溯时要把数组改回来。
参考代码:
int fr[100010],ne[100010];
int v[100010],bs=0;
int fj[1000010][22],gs[1000010];
bool sa[1000010];
int ss[1000010],sd[100010];
int tt[1000010];
void ycl()
{
int sl=0;
for(int i=2;i<=1000000;i++)
{
if(!sa[i])
{
ss[sl++]=i;
fj[i][0]=i;
gs[i]=1;
}
for(int j=0;j<sl;j++)
{
if((long long)i*ss[j]>1000000)
break;
for(int k=0;k<gs[i];k++)
fj[i*ss[j]][k]=fj[i][k];
fj[i*ss[j]][gs[i]]=ss[j];
gs[i*ss[j]]=gs[i]+1;
sa[i*ss[j]]=true;
if(i%ss[j]==0)
break;
}
}
sd[1]=1;
}
void addb(int a,int b)
{
v[bs]=b;
ne[bs]=fr[a];
fr[a]=bs;
bs+=1;
}
int sz[100010],jg[100010];
void dfs(int u,int wz[1000010])
{
int yu[22];
for(int i=0;i<gs[sz[u]];i++)
{
int z=fj[sz[u]][i];
if(wz[z]==u)
continue;
if(sd[wz[z]]>sd[jg[u]])
jg[u]=wz[z];
yu[i]=wz[z];
wz[z]=u;
}
for(int i=fr[u];i!=-1;i=ne[i])
{
sd[v[i]]=sd[u]+1;
dfs(v[i],wz);
}
for(int i=0;i<gs[sz[u]];i++)
{
if(wz[fj[sz[u]][i]]==u)
wz[fj[sz[u]][i]]=yu[i];
}
}
int main()
{
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
ycl();
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
fr[i]=-1;
scanf("%d",&sz[i]);
}
for(int i=0;i<n-1;i++)
{
int a,b;
scanf("%d%d",&a,&b);
addb(a,b);
}
dfs(1,tt);
for(int i=1;i<=n;i++)
{
if(jg[i]==0)
printf("-1\n");
else
printf("%d\n",jg[i]);
}
fclose(stdin);
fclose(stdout);
return 0;
}