Educational Codeforces Round 58 (Rated for Div. 2) D.GCD Counting(樹的直徑+gcd)
阿新 • • 發佈:2019-01-12
題意
思路來源
Codeforce__JuRuo
題解
將每個gcd分解素因子放入對應vector
相當於對每個素因子建了一棵樹
遍歷每個素因子的樹,尋找直徑,更新答案
注意C++11的寫法 好好學學 會省不少功夫
還有一些技巧性寫法 加油!
程式碼
#include<bits/stdc++.h> using namespace std; #define ll __int64 const int maxn=2e5+10; int n,a[maxn],vis[maxn],vis1[maxn],ans=1,flag=1,md,mp,p[maxn]; struct edge { int u,v; edge(int uu,int vv):u(uu),v(vv){ } }; vector<edge>e[maxn]; vector<int> v[maxn]; void dfs(int p,int d,int *vis) { if(vis[p])return;//溯父 不影響 vis[p]=1; if(d>md)md=d,mp=p; for(int i=0;i<v[p].size();++i) dfs(v[p][i],d+1,vis); } int gcd(int a,int b) { return b?gcd(b,a%b):a; } int main() { for(ll i=2;i<maxn;++i) { if(!p[i]) { for(ll j=i*i;j<maxn;j+=i) p[j]=1; } } scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",a+i),a[i]>1&&(flag=0);//短路判均<=1 } if(flag) { puts("0"); return 0; } for(int i=1;i<n;++i) { int u,v,k; scanf("%d%d",&u,&v); if((k=gcd(a[u],a[v]))>1) { for(int j=1;j*j<=k;++j)//j從1開始是為了判k { if(k%j==0) { if(!p[j]&&j!=1)e[j].push_back(edge(u,v)); if(j*j!=k&&!p[k/j])e[k/j].push_back(edge(u,v)); } } } } for(int i=2;i<maxn;++i) { if(!p[i]) { vector<int> p; for(int j=0;j<e[i].size();++j) { edge& E=e[i][j]; p.push_back(E.u); p.push_back(E.v); v[E.u].push_back(E.v); v[E.v].push_back(E.u); } for(int j=0;j<p.size();++j) { vis[p[j]]=vis1[p[j]]=0; } for(int j=0;j<p.size();++j) { if(!vis[p[j]]) { md=0; dfs(p[j],1,vis); md=0; dfs(mp,1,vis1); ans=max(ans,md); } } for(int j=0;j<p.size();++j) v[p[j]].clear(); } } printf("%d\n",ans); return 0; }