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(树上莫比乌斯反演,分层图,并查集)