传送门
虽然说这题有简单的方法,可是这其实是个点分治裸题欸
假设当前的分治到的重心为 x x x,很显然,经过 x x x的那些合法的链,肯定链中每个数都含有起码一个相同的 a [ x ] a[x] a[x]的质因子,因为 g c d ∣ a [ x ] gcd|a[x] gcd∣a[x]嘛。把 a [ x ] a[x] a[x]分解质因数,然后对每个质因子 p p p,都做一次dfs,求出离 x x x最远的两个点 u , v u,v u,v,这两个点到x的路径上的数当然都要被 p p p整除,然后 a n s = m a x ( a n s , d i s ( u ) + d i s ( v ) ) ans=max(ans,dis(u)+dis(v)) ans=max(ans,dis(u)+dis(v)), d i s ( u ) dis(u) dis(u)表示 u u u到 x x x的距离。要注意 u , v u,v u,v不能在一个子树内。
然后每次找重心,不停把树分割就行了。
点分治码量比较大,但是熟练之后打起来其实还是挺快的。。大多都是板子,比赛的时候复制粘贴23333
代码丑哭。。写不来点分。。。。
#include
#pragma GCC optimize("Ofast")
#define ll long long
#define fr(i,x,y) for(int i=(x);i<=(y);i++)
#define rf(i,x,y) for(int i=(x);i>=(y);i--)
#define frl(i,x,y) for(int i=(x);i<(y);i++)
using namespace std;
const int N=200002;
const int M=N<<1;
int n,a[N];
int cnt,head[N],Next[M],v[M];
int b[N];
int rt,mx,mxx;
int sz[N],mmx[N],s[M];
int ans=-1;
vector<int> p[N];
void read(int &x){
char ch=getchar();x=0;
for(;ch<'0'||ch>'9';ch=getchar());
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
}
void add(int x,int y){
Next[++cnt]=head[x];
head[x]=cnt;
v[cnt]=y;
}
int findrt(int x,int fa,int n){ //找重心
sz[x]=1;mmx[x]=0;
int ans=0,tt;
for(int i=head[x];i;i=Next[i])
if (v[i]!=fa&&!b[v[i]]){
tt=findrt(v[i],x,n);
if (mmx[tt]<mmx[ans]) ans=tt;
sz[x]+=sz[v[i]];
mmx[x]=max(mmx[x],sz[v[i]]);
}
mmx[x]=max(mmx[x],n-sz[x]);
if (mmx[x]<mmx[ans]) ans=x;
return ans;
}
int getdis(int x,int fa,int vv){
int mx=0;
for(int i=head[x];i;i=Next[i])
if (v[i]!=fa&&!b[v[i]]&&a[v[i]]%vv==0)
mx=max(mx,getdis(v[i],x,vv));
return mx+1;
}
int cal(int x,int vv){ //找最远的两个点
ans=max(ans,0);
int mx=-1,mxx=-1;
for(int i=head[x];i;i=Next[i])
if (!b[v[i]]&&a[v[i]]%vv==0){
int xx=getdis(v[i],x,vv);
if (xx>mx) mx=xx;
if (mx>mxx) swap(mx,mxx);
}
return max(mx+mxx,mxx);
}
void dfs(int x,int n){ //分割树
b[x]=1;int tmp=a[x];
frl(i,0,p[tmp].size())
ans=max(ans,cal(x,p[tmp][i])); //对每个质因子都找最远的
for(int i=head[x];i;i=Next[i])
if (!b[v[i]]){
int rt=findrt(v[i],0,sz[v[i]]);
assert(rt>0);
dfs(rt,s[i]);
}
}
void init(){ //分解质因数
frl(i,2,N)
if (!b[i]){
p[i].push_back(i);
for(int j=2*i;j<N;j+=i)
p[j].push_back(i),b[j]=1;
}
memset(b,0,sizeof b);
}
int main(){
init();
read(n);
fr(i,1,n) read(a[i]);
int x,y;
fr(i,2,n){
read(x);read(y);
add(x,y);add(y,x);
}
//int rt=findrt(1,0,n);
mmx[0]=2e9;
dfs(findrt(1,0,n),n);
cout<<ans+1<<endl;
return 0;
}