Educational Codeforces Round 58 (Rated for Div. 2) D. GCD Counting

D. GCD Counting

time limit per test

4.5 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a tree consisting of nn vertices. A number is written on each vertex; the number on vertex ii is equal to aiai.

Let's denote the function g(x,y)g(x,y) as the greatest common divisor of the numbers written on the vertices belonging to the simple path from vertex xx to vertex yy (including these two vertices). Also let's denote dist(x,y)dist(x,y) as the number of vertices on the simple path between vertices xx and yy, including the endpoints. dist(x,x)=1dist(x,x)=1 for every vertex xx.

Your task is calculate the maximum value of dist(x,y)dist(x,y) among such pairs of vertices that g(x,y)>1g(x,y)>1.

Input

The first line contains one integer nn — the number of vertices (1≤n≤2⋅105)(1≤n≤2⋅105).

The second line contains nn integers a1a1, a2a2, ..., anan (1≤ai≤2⋅105)(1≤ai≤2⋅105) — the numbers written on vertices.

Then n−1n−1 lines follow, each containing two integers xx and yy (1≤x,y≤n,x≠y)(1≤x,y≤n,x≠y) denoting an edge connecting vertex xx with vertex yy. It is guaranteed that these edges form a tree.

Output

If there is no pair of vertices x,yx,y such that g(x,y)>1g(x,y)>1, print 00. Otherwise print the maximum value of dist(x,y)dist(x,y) among such pairs.

Examples

input 

3
2 3 4
1 2
2 3

output 

1

input 

3
2 3 4
1 3
2 3

output 

2

input 

3
1 1 1
1 2
2 3

output 

0

 

已知n个节点上的权值,又告诉了n - 1条边,查询在这棵树上是否存在一条路径,这条路径上每个节点两两之间的gcd > 2,求这条路径的最长长度。 不存在这种路径则输出0

 

首先,对于每次输入边集的时候,求出gcd, 分解gcd,对于分解出来的因子,把u~v这条边存进去,也就是打一个素信息表,

然后去枚举可能存在的素因子,对于每个可能的素因子,取出来素信息表里的边集,重新建图,在每次的图中,跑最长链(dp、dfs都可以,个人不会dp,bfs要超时,因为可能存在图内不联通的情况,被这个坑了好久)

 

代码如下:

#include 

using namespace std;

typedef long long ll;
typedef pair  P;

const int maxn = 2e5 + 1e4;
vector >v;
vector

E[maxn]; ll a[maxn]; int prime[maxn + 20]; int vis[maxn + 20]; int cnt = 0; int marked[maxn]; vector >Map; int id1 = 0,id2 = 0; void dfs(int x,int fa,int sum) { // cout << x << endl; marked[x] = 1; if(sum > id2) { id2 = sum,id1 = x; } for(auto const d:v[x]) { if(d != fa) dfs(d,x,sum + 1); } return ; } void Init() { cnt = 0 ; memset(vis,0,sizeof(vis)); memset(marked,0,sizeof(marked)); vis[0] = vis[1] = 1; for(int i = 2; i <= maxn; i++) { if(!vis[i]) { prime[cnt++] = i; for(int j = i + i; j <= maxn; j += i) vis[j] = 1; } } return ; } int main() { int n,m; Init(); // for(int i = 0;i < 10;i++) cout << prime[i] << endl; while(cin >> n) { ll Max = 0; setpr; for(int i = 1; i <= n; i++) cin >> a[i],Max = max(Max,a[i]); for(int i = 1; i < n; i++) { int u,vv; cin >> u >> vv; int gcd = __gcd(a[u],a[vv]); for(int j = 2; j * j <= gcd; j++) { if(gcd % j == 0) { E[j].push_back(P(u,vv)); pr.insert(j); while(gcd % j == 0) gcd /= j; } } if(gcd > 1) { E[gcd].push_back(P(vv,u)); pr.insert(gcd); } } if(Max == 1){ cout << 0 << endl; continue; } int ans = 0; for(auto const x:pr) { v.clear(); v.resize(200000 + 50); sets; // cout << x << endl; for(auto const d:E[x]) { int u = d.first; int vv = d.second; s.insert(u); v[u].push_back(vv); v[vv].push_back(u); } for(auto ss:s) { if(!marked[ss]) { id1 = -1,id2 = 0; dfs(ss,0,0); if(id1 != -1) { marked[ss] = 0; dfs(id1,0,0); ans = max(ans,id2); } } } } cout << ans + 1 << endl; } return 0; }

 

你可能感兴趣的:(Codeforces,树形dp)