CF1101D GCD Counting 题解

好古早的题目,模拟赛考的。


赛后想到了一个和题解都不是很像的方法(貌似交不了题解,直接在这里写吧)。(有点卡常)

想的是一个u可以到达点v,当且仅当它们有大于等于一个公共因数p。那就可以根据这个限制条件建立一个分层图,每个点内两两连通,直接求这个连通分量的直径最后再去max。

但是如果要重新建新图的话,算了一下空间有点炸。所以可以采用类似同余最短路的思想,如果两个点有相同的因数那么就可以互相到达。遍历每一个因子,跑图就可以。

感觉讲的不是很清楚,把代码加个注释吧。

#include <bits/stdc++.h>
#define int long long
using namespace std ;

const int N=2e5+10 ;
vector<int> g[N],upg[N];
int dis[N],dep[N],fa[N][25],lg[N] ;
vector<int> havp[N] ;
// 权值有p这个因数的节点
bool vis[N] ; vector<int> scc ;

void getscc(int u,int p) { //找连通块
	vis[u]=1 ; // 在连通块内
	scc.push_back(u) ;
	for(int v:g[u]) if(vis[v]==0&&dis[v]%p==0) // 如果dis[v]有p这个质因子,可以互相到达
		getscc(v,p) ;
}
void dfsfar(int u,int f,int p,int depth,int &mxdep,int &res) {
	// 找离u最远的far1,mxdep:scc内直径
	if(depth>mxdep) {mxdep=depth ;res=u ;}
	for(auto v:g[u]) {
		if(v==f) continue ;
		if(dis[v]%p==0) dfsfar(v,u,p,depth+1,mxdep,res) ;
	}
}
int getdiam(int u,int p) {
	int far1=u,mxdep=0 ;
	dfsfar(u,0,p,0,mxdep,far1) ;
	int far2=far1 ; mxdep=0 ;
	dfsfar(far1,0,p,0,mxdep,far2) ;
	return mxdep+1 ;
	// 本身也算一个所以+1
}

signed main() {
//	freopen("counting.in","r",stdin) ;
//	freopen("counting.out","w",stdout) ;
	ios::sync_with_stdio(0) ; cin.tie(0) ; cout.tie(0) ;
	
	int n ; cin>>n ;
	bool flag=1 ;
	for(int i=1;i<=n;i++) { //预处理 O(n sqrt(V))
		cin>>dis[i] ; int d=dis[i] ;
		if(dis[i]!=1) flag=0 ;
		for(int pj=2;pj*pj<=d;pj++) if(d%pj==0) { //分解质因数
			havp[pj].push_back(i) ;
			while(d%pj==0) d/=pj ; 
		}
		if(d>1) havp[d].push_back(i) ;
	}
	for(int i=1,u,v;i<n;i++) {
		cin>>u>>v ;
		g[u].push_back(v) ; g[v].push_back(u) ;
	}
	if(flag) return cout<<0,0 ; //特判无解
	
	int ans=0 ;
	for(int p=2;p<=2e5;p++) { //找答案 O(n sqrt(V))
		if(havp[p].empty()) continue ; //如果没有节点有p这个因数,就继续下一个
		memset(vis,0,sizeof(vis)) ;
		for(auto u:havp[p]) { 
			if(vis[u]||dis[u]%p!=0) continue ; //如果u已经在scc里面,就找下一个
			scc.clear() ; scc.shrink_to_fit() ;
			getscc(u,p) ;
			int diam=getdiam(scc[0],p) ;
			ans=max(ans,diam) ;
		}
	}
	cout<<ans ;
	
	return 0 ;
}
/*
O(n sqrt(V))

赛时构的样例:

8
2 2 2 4 5 6 6 8
1 2
2 4
4 7 
4 8
2 5
5 6
1 3
*/
posted @ 2026-09-07 15:15  Emumumu  阅读(6)  评论(0)    收藏  举报