挺简单的树dp,两个点之间的公共素因子不会超过7个,枚举和子节点之间的公共素因子情况,有公共素因子就可以转移,长谷ide树dp去做就行了。
代码:
#include <bits/stdc++.h>
#define ps push_back
using namespace std;
const int maxn=2e5+5;
int a[maxn], ans;
int d[maxn][8];
int cnt[maxn];
int dp[3][8][maxn];
int s[30], mp[30];
vector<int> edg[maxn];
void dfs(int x, int fa)
{
int ma[8][3];
memset(ma, 0, sizeof(ma));
for(int i=0; i<cnt[x]; i++)
{
dp[0][i][x]=dp[1][i][x]=1;
}
for(int i=0; i<edg[x].size(); i++)
{
int to=edg[x][i];
if(to!=fa)
{
dfs(to, x);
for(int j=0; j<cnt[x]; j++)
{
for(int k=0; k<cnt[to]; k++)
{
if(d[x][j]==d[to][k])
{
dp[0][j][x]=max(dp[0][j][x], dp[0][k][to]+1);
ma[j][1]=max(ma[j][1], dp[0][k][to]+1);
if(ma[j][1]>ma[j][0])swap(ma[j][1],ma[j][0]);
}
}
}
}
}
for(int i=0; i<cnt[x]; i++)
{
if(ma[i][1]>0)
{
dp[1][i][x]=max(dp[1][i][x], ma[i][1]+ma[i][0]-1);
ans=max(ans, dp[1][i][x]);
}
ans=max(ans, dp[0][i][x]);
}
return;
}
int main()
{
int i, j, num=1;
int n;
cin>>n;
for(i=1; i<=n; i++)
{
scanf("%d", &a[i]);
int x=a[i];
for(int j=2; j<=sqrt(x); j++)
{
if(x%j==0)
{
d[i][cnt[i]++]=j;
while(x%j==0)x/=j;
}
}
if(x>1)d[i][cnt[i]++]=x;
}
for(int i=1; i<n; i++)
{
int x, y;
scanf("%d%d", &x, &y);
edg[x].ps(y);
edg[y].ps(x);
}
dfs(1,1);
// if(ans==1)ans=0;
cout<<ans<<endl;
return 0;
}