/ * Tree Mobius inversion seeking tree satisfying d | gcd (au, av) gcd (au, av) log f (d) How to get: establishing a new layer of FIG. 200,000, i.e., establishing for each of the number of a new map at the plus side when a uv gcd (au, av) FIG divisor layer edging f [i] represents a number satisfying the condition i i-th layer | gcd (a [u], a [v]) logarithmic, then again find disjoint-set, update f [i] in the merge process can, keeping in mind f [i] the initial value of the number of active nodes of this layer, the corresponding i | gcd (a [u] , a [u]) of such a case is then used to find the final answer Mobius inversion G [D] = Sigma (U [I] * F [I * D]) * / #include <bits / STDC ++. H > the using namespace STD; #define MAXN 200005 int Phi [MAXN], MU [MAXN], Prime [MAXN], m; BOOL VIS [MAXN]; void the init () { // play table MU Phi [ . 1 ] MU = [ 1 ] = 1 ; for(int i=2;i<maxn;i++){ if(!vis[i]){ mu[i]=-1;prime[++m]=i;phi[i]=i-1; } for(int j=1;j<=m;j++){ if(i*prime[j]>=maxn)break; vis[i*prime[j]]=1; if(i%prime[j]==0){ phi[i*prime[j]]=phi[i]*prime[j]; mu[i*prime[j]]=0; break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1),mu[i*prime[j]]=-mu[i]; } } } int n,a[maxn]; long long f[maxn],u[maxn],v[maxn]; vector<int>vec[maxn];//每层的边的下标集合 int F[maxn],size[maxn]; int find(int x){ return F[x]==x?x:F[x]=find(F[x]); } void bing(int i,int u,int v){ int t1=find(u),t2=find(v); if(t1==t2)return; f[i]+=(long long)size[t1]*size[t2]; size[t1]+=size[t2];F[t2]=t1; } int main(){ init(); cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; for(int j=1;j*j<=a[i];j++) if(a[i]%j==0){ f[j]++; if(a[i]/j!=j)f[a[i]/j]++; } } for(int i=1;i<n;i++){//建立2000000层新图 scanf("%d%d",&u[i],&v[i]); int tmp=__gcd(a[u[i]],a[v[i]]); for(int j=1;j*j<=tmp;j++) if(tmp%j==0){ vec[j].push_back(i); if(tmp/j!=j) VEC [tmp / J] .push_back (I); } } // find disjoint-set for ( int I = . 1 ; I <= 200000 ; I ++ ) { for ( int J = 0 ; J <VEC [I] .size (); J ++) { // initialize each corresponding disjoint-set int Uu = U [VEC [I] [J]], VV = V [VEC [I] [J]]; F. [Uu] = Uu ; F. [VV] = VV; size [Uu] = . 1 ; size [VV] = . 1 ; } for ( int J = 0; J <VEC [I] .size (); J ++) { // then combined evaluated int Uu = U [VEC [I] [J]], VV = V [VEC [I] [J]]; Bing (I, Uu, VV); } } // inversion + output for ( int D = . 1 ; D <= 200000 ; D ++ ) { Long Long ANS = 0 ; for ( int I = . 1 ; I * D <= 200000 ; I ++ ) ANS + = ( Long Long ) MU [I] * F [I * D]; IF (ANS =! 0 ) cout<<d<<" "<<ans<<'\n'; } }