CF1101D GCD Counting 点分治+质因数分解

Posted guangheli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1101D GCD Counting 点分治+质因数分解相关的知识,希望对你有一定的参考价值。

想到本质不同质因数不会很多就切了~

 

Code: 

#include <cstdio> 
#include <vector> 
#include <algorithm> 
#define N 200004  
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std; 
int n,tot,edges,sn,root,tl,answer; 
vector<int>v[N];   
int prime[N],is[N],num[N]; 
int val[N],hd[N],to[N<<1],nex[N<<1];       
int size[N],mx[N],vis[N],f[N],g[N],tmp[N],depth[N],cur[N],number[N];          
void add(int u,int v) 

    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;    
     
void getroot(int u,int ff) 

    size[u]=1,mx[u]=0; 
    for(int i=hd[u];i;i=nex[i]) 
        if(to[i]!=ff&&!vis[to[i]]) 
            getroot(to[i],u),size[u]+=size[to[i]],mx[u]=max(mx[u],size[to[i]]); 
    mx[u]=max(mx[u],sn-size[u]); 
    if(mx[u]<mx[root]) root=u;    
   
void dfs(int u,int ff,int dep) 
    
    number[u]=tmp[++tl]=__gcd(val[u],number[ff]),depth[tl]=dep;       
    for(int i=hd[u];i;i=nex[i]) 
        if(to[i]!=ff&&!vis[to[i]])      
            dfs(to[i],u,dep+1);     

void calc(int u) 
   
    int i,j,re;      
    if(val[u]>1) answer=max(answer,1);  
    tl=0;      
    number[u]=val[u];   
    for(i=hd[u];i;i=nex[i]) 
    
        if(vis[to[i]]) continue;    
        re=tl+1,dfs(to[i],u,1);     
        for(j=re;j<=tl;++j) 
        
            int a=tmp[j],b=depth[j];  
            if(a>1) 
             
                for(int k=0;k<v[a].size();++k) 
                    g[v[a][k]]=max(g[v[a][k]],b),answer=max(answer,g[v[a][k]]+f[v[a][k]]+1);    
            
                  
        for(j=re;j<=tl;++j) 
        
            int a=tmp[j];       
            if(a>1) 
            
                for(int k=0;k<v[a].size();++k) f[v[a][k]]=max(f[v[a][k]],g[v[a][k]]);    
            
              
        for(j=re;j<=tl;++j) 
        
            int a=tmp[j]; 
            if(a>1) for(int k=0;k<v[a].size();++k) g[v[a][k]]=0; 
        
     
    for(i=1;i<=tl;++i) 
    
        int a=tmp[i]; 
        if(a>1) for(j=0;j<v[a].size();++j) f[v[a][j]]=g[v[a][j]]=0;   
    

void solve(int u) 
 
    vis[u]=1,calc(u);    
    for(int i=hd[u];i;i=nex[i]) 
        if(!vis[to[i]]) 
            sn=size[to[i]],root=0,getroot(to[i],u),solve(root);

void init() 
 
    int i,j;  
    for(i=2;i<N;++i) 
    
        if(!is[i]) prime[++tot]=i;            
        for(j=1;j<=tot&&i*prime[j]<N;++j) 
        
            is[i*prime[j]]=1;            
            if(i%prime[j]==0) break;       
          
        
    for(i=2;i<N;++i) num[i]=i; 
    for(i=1;i<=tot;++i) 
        for(j=prime[i];j<N;j+=prime[i])   
         
            v[j].push_back(prime[i]);    
            while(num[j]%prime[i]==0) num[j]/=prime[i];   
        

int main() 

    int i,j;    
    init();    
    // setIO("input");  
    scanf("%d",&n); 
    for(i=1;i<=n;++i) scanf("%d",&val[i]); 
    for(i=1;i<n;++i) 
    
        int a,b; 
        scanf("%d%d",&a,&b),add(a,b),add(b,a);   
       
    mx[root=0]=sn=n,getroot(1,0),solve(root);
    printf("%d\n",answer);       
    return 0;    
         

  

以上是关于CF1101D GCD Counting 点分治+质因数分解的主要内容,如果未能解决你的问题,请参考以下文章

CF EDU 1101D GCD Counting 树形DP + 质因子分解

Codeforces990 G. GCD Counting(点分治)

CF990G GCD Counting(树上莫比乌斯反演,分层图,并查集)

CodeForces990G:GCD Counting(树分治+GCD)

CF1303G(点分治+李超线段树)

UOJ树上gcd