CF1101D GCD Counting
题目链接
题意分析
求解最长路径的问题 我们可以使用DP
但是这里求GCD比较恶心 我们可以转换思路
gcd(x,y)≠1 说明x,y之间必然存在公共质因子 那么我们可以通过枚举质因子代替gcd
由于2×3×5×7×11×13×17×19=9699690>200000 所以枚举质因子对于复杂度几乎无影响
然后使用树形DP就可以了
CODE:
#include<bits/stdc++.h>
#define M 408611
#define INF 200080
using namespace std;
int n,tot,cnt,root,sum,ans;
int num[M];
int to[M],nex[M],head[M];
int dp[M][10];
int prime[M];
bool mark[M];
vector<int> G[M];
void add(int x,int y)
{to[++tot]=y;nex[tot]=head[x];head[x]=tot;}
void pre()
{
for(int i=2;i<=INF;++i)
{
if(!mark[i]) prime[++tot]=i;
for(int j=1;j<=tot&&prime[j]*i<=INF;++j)
{
mark[prime[j]*i]=1;
if(i%prime[j]==0) break;
}
}
for(int i=1;i<=tot;++i)\\预处理质因子
for(int j=prime[i];j<=INF;j+=prime[i])
G[j].push_back(prime[i]);
}
void dfs(int now,int fat)
{
for(int i=0;i<(int)G[num[now]].size();++i) dp[now][i]=1;
for(int x=head[now];x;x=nex[x])
{
int v=to[x];
if(v==fat) continue;
dfs(v,now);
for(int i=0;i<(int)G[num[now]].size();++i)
for(int j=0;j<(int)G[num[v]].size();++j)
{//枚举质因子 如果存在相同的话就转移
if(G[num[now]][i]!=G[num[v]][j]) continue;
ans=max(ans,dp[now][i]+dp[v][j]);
dp[now][i]=max(dp[now][i],dp[v][j]+1);
}
}
}
int main()
{
pre();tot=0;
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%d",&num[i]);
if(num[i]>1) ans=1;
}
for(int i=1,x,y;i<n;++i)
{
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
dfs(1,0);
printf("%d\n",ans);
return 0;
}