FIG hierarchical tree Mobius inversion + disjoint-set --cf990G

/ * 
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';
    } 
}

 

Guess you like

Origin www.cnblogs.com/zsben991126/p/11117356.html
Recommended