You are given a tree consisting of n vertices. A number is written on each vertex; the number on vertex i is equal to ai
.
Let's denote the function g
as the greatest common divisor of the numbers written on the vertices belonging to the simple path from vertex x to vertex y (including these two vertices). Also let's denote d as the number of vertices on the simple path between vertices x and y, including the endpoints. d for every vertex x
.
Your task is calculate the maximum value of d
among such pairs of vertices that g
.
InputThe first line contains one integer n
— the number of vertices (1≤n≤2⋅105).
The second line contains n
integers a1, a2, ..., an (1≤ai≤2⋅105)— the numbers written on vertices.
Then n−1
lines follow, each containing two integers x and y (1≤x,y denoting an edge connecting vertex x with vertex y. It is guaranteed that these edges form a tree.
OutputIf there is no pair of vertices x,y
such that g, print 0. Otherwise print the maximum value of damong such pairs.
Examples3
2 3 4
1 2
2 3
1
3
2 3 4
1 3
2 3
2
3
1 1 1
1 2
2 3
0
題意:讓你求最長的路徑長度,滿足路上gcd不為1;
思路:分治的做法比較暴力,但是時限比較長,有板子就直接上了。 由於gcd具有收斂性,路徑上的gcd不會太多,而且越遠回越接近1,我們記錄每一個gcd的最深的位置即可。 (我用的以前的板子,所以用了map,此題的數據量可以不用map
還有一個思路,我們枚舉素因子,然后把含有這個素因子的點標記出來,求他們的最遠距離,更新答案。
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=200010; const int inf=0x7FFFFFFF; int Laxt[maxn],Next[maxn<<1],To[maxn<<1],cnt,N,sn; int a[maxn],sz[maxn],son[maxn],vis[maxn],root,res; int dep[maxn]; ll ans[maxn]; map<int,int>mp,tp; map<int,int>::iterator it1,it2; inline void read(int &x) { x=0; char c=getchar(); while(c>'9'||c<'0') c=getchar(); while(c<='9'&&c>='0') x=(x<<3)+(x<<1)+c-'0',c=getchar(); } void add(int u,int v){ Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; } void getroot(int u,int fa) //找重心 { sz[u]=1; son[u]=0; for(int i=Laxt[u];i;i=Next[i]){ if(To[i]!=fa&&!vis[To[i]]){ getroot(To[i],u); sz[u]+=sz[To[i]]; son[u]=max(son[u],sz[To[i]]); } } son[u]=max(son[u],sn-son[u]); if(root==0||son[root]>son[u]) root=u; } void getans(int u,int fa,int num) //對於當前鏈產生的新GCD { dep[u]=dep[fa]+1; tp[num]=max(tp[num],dep[u]); for(int i=Laxt[u];i;i=Next[i]){ if(!vis[To[i]]&&To[i]!=fa){ getans(To[i],u,__gcd(num,a[To[i]])); } } } void solve(int u) //解決以u為根的子問題 { mp.clear(); mp[a[u]]=1; ans[a[u]]++; dep[u]=1; for(int i=Laxt[u];i;i=Next[i]) if(!vis[To[i]]) { tp.clear(); getans(To[i],u,__gcd(a[u],a[To[i]])); for(it1=mp.begin();it1!=mp.end();it1++) for(it2=tp.begin();it2!=tp.end();it2++){ int g=__gcd((*it1).first,(*it2).first); if(g>1) res=max(res,(*it1).second+(*it2).second-1); } for(it2=tp.begin();it2!=tp.end();it2++) mp[(*it2).first]=max((*it2).second,mp[(*it2).first]); } } void dfs(int u) //分治 { vis[u]=1; solve(u); for(int i=Laxt[u];i;i=Next[i]){ if(vis[To[i]]) continue; root=0; sn=sz[To[i]]; getroot(To[i],0); dfs(root); } } int main() { read(N); int u,v,Max=0; for(int i=1;i<=N;i++) read(a[i]),Max=max(Max,a[i]); for(int i=1;i<N;i++) { read(u);read(v); add(u,v); add(v,u); } if(Max>1) res=1; root=0; sn=N; getroot(1,0); dfs(root); printf("%d\n",res); return 0; }