[LOJ#6159][美团 CodeM 初赛 Round A][暴力即正解]最长树链

枚举每一个质数,权值是这个质数的倍数的节点设为1,否则为0,那么最长长链的长度就是点权为1的点构成的最长的链。

当然不用枚举所以质数,因为每个数最多有log个不同的质因数,所以只要把所有点权质因数分解,枚举出现的质数就可以了。

枚举质数后dfs,复杂度是nlogn的,因为每个点有log个不同的质因数,也就是说最多枚举到log个质数要dfs这个节点,所以复杂度是对的

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#define pb push_back

using namespace std;

const int N=100010;

int n,u,v,cnt,L,ans;
int p[N],vis[N],a[N],pnt;

map<int,vector<int> > M;
vector<int> e[N];

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void rea(int &x){
  char c=nc(); x=0;
  for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

inline void Pre(int n){
  for(int i=2;i<=n;i++){
    if(!p[i]) p[++pnt]=i;
    for(int j=1;j<=pnt&&1LL*i*p[j]<=n;j++){
      p[p[j]*i]=1;
      if(i%p[j]==0) break;
    }
  }
}

void dfs(int u,int f,int p){
  L++; vis[u]=p;
  for(int v : e[u])
    if(v!=f&&a[v]%p==0) dfs(v,u,p);
}

int main(){
  rea(n); Pre(100000);
  for(int i=1;i<n;i++)
    rea(u),rea(v),e[u].pb(v),e[v].pb(u);
  for(int i=1;i<=n;i++){
    int x; rea(x); a[i]=x;
    for(int j=1;j<=pnt&&1LL*p[j]*p[j]<=x;j++)
      if(x%p[j]==0){
    while(x%p[j]==0) x/=p[j];
    M[p[j]].pb(i);
    if(x==1) break;
      }
    if(x!=1) M[x].pb(i);
  }
  for(auto s : M){
    int p=s.first;
    vector<int> v=s.second;
    for(int u : v)
      if(vis[u]!=p){
    L=0; dfs(u,0,p);
    ans=max(ans,L);
      }
  }
  printf("%d\n",ans); return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值