1. 程式人生 > >codeforces1101D GCD Counting 【樹形DP】

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 }