codeforces1101D GCD Counting 【树形DP】

题目分析:

蛮简单的一道题,对于每个数拆质因子,对于每个质因子找出最长链,在每个地方枚举一下拼接

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 205000;
 5 
 6 int n,a[maxn],prime[maxn],flag[maxn],minn[maxn],num,ans;
 7 vector <int> g[maxn];
 8 vector <pair<int,int> > mp[maxn];
 9 
10 vector<int> cl[maxn];
11 
12 void getprime(int N){
13     for(int i=2;i<=N;i++){
14     if(!flag[i]){prime[++num] = i,minn[i] = i;}
15     for(int j=1;j<=num&&i*prime[j]<=N;j++){
16         flag[i*prime[j]] = 1;
17         minn[i*prime[j]] = prime[j];
18         if(i%prime[j] == 0) break;
19     }
20     }
21 }
22 
23 void read(){
24     scanf("%d",&n);
25     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
26     for(int i=1;i<n;i++){
27     int u,v; scanf("%d%d",&u,&v);
28     g[u].push_back(v); g[v].push_back(u);
29     }
30 }
31 
32 void dp(int now,int fa){
33     for(int i=0;i<g[now].size();i++){
34     if(g[now][i] == fa) continue;
35     dp(g[now][i],now);
36     }
37     int p = a[now];
38     while(p != 1){cl[minn[p]].clear(); p /= minn[p]; }
39     for(int i=0;i<g[now].size();i++){
40     if(g[now][i] == fa) continue;
41     for(int j=0;j<mp[g[now][i]].size();j++){
42         if(a[now] % mp[g[now][i]][j].first == 0){
43         cl[mp[g[now][i]][j].first].push_back(mp[g[now][i]][j].second);
44         }
45     }
46     }
47     p = a[now];
48     while(p != 1){
49     int z = minn[p]; while(p%z == 0) p /= z;
50     int maxx = 0,sec = 0;
51     for(int i=0;i<cl[z].size();i++){
52         if(cl[z][i] >= maxx) sec = maxx,maxx = cl[z][i];
53         else if(cl[z][i] > sec) sec = cl[z][i];
54     }
55     mp[now].push_back(make_pair(z,maxx+1));
56     ans = max(ans,maxx+sec+1);
57     }
58 }
59 
60 void work(){
61     getprime(200000);
62     dp(1,0);
63     printf("%d\n",ans);
64 }
65 
66 int main(){
67     read();
68     work();
69     return 0;
70 }

猜你喜欢

转载自www.cnblogs.com/Menhera/p/10265127.html