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;
} 
原文地址:https://www.cnblogs.com/tcswuzb/p/14457223.html