Codeforces | 1101D GCD Counting | 动态规划 | 树规
Description
给出一棵树,树有点权,求树上长度最长的一条链,满足链上所有点的点权的 $\gcd > 1$。一个点也算一条链。
Input Format
第一行一个正整数 $n$ 表示树的点数。
接下来一行 $n$ 个正整数 $a_i$ 表示每个点的点权。
接下来 $n-1$ 行每行两个正整数 $u,v$ 表示树上的一条边。
Output Format
一行一个整数,如果不存在这样的链输出
0
,否则输出最长的可能链长。
Input Sample
Sample 01
3
2 3 4
1 2
2 3
Sample 02
3
2 3 4
1 3
2 3
Sample 03
3
1 1 1
1 2
2 3
Output Sample
Sample 01
1
Sample 02
2
Sample 03
0
Data Range
$1 \le n,a_i \le 2 \times 10^5$。
Solution
树归。考虑分解每个点的质因子。
设 $F[i][j]$ 表示结点 $i$ 的第 $j$ 个质因子向下能够延伸的最长长度。由于因子个数极少,枚举转移即可。
Code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
#define swap(x,y) {int t=x; x=y,y=t;}
#define wipe(x,y) memset(x,y,sizeof(x))
#define dbgIn(x) freopen(x".in","r+",stdin)
#define rep(x,y,z) for(int x=y,I=z;x<=I;++x)
#define dbgOut(x) freopen(x".out","w+",stdout)
#define file(x) freopen(x".in","r+",stdin); freopen(x".out","w+",stdout)
using std::lower_bound;
inline void Read(int &x){
x=0; char ch=0; while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar(); return;
}
struct edge{
int from;
int to;
int next;
}e[400005];
int N;
int po;
int ans;
int cnt;
int node;
int w[200005];
int primes[20005];
int first[200005];
int last[200005];
int f[200005][9];
int d[200005][9];
bool vis[200005];
bool isprime[200005];
void addedge(int u,int v){
e[++node]=(edge){u,v,0};
if(first[u]==0) first[u]=node;
else e[last[u]].next=node;
last[u]=node; return;
}
void Euler_Sieve(int Lim){
rep(i,2,Lim){
if(!isprime[i])
primes[++cnt]=i;
for(int j=1;j<=cnt&&i*primes[j]<=Lim;j++){
isprime[i*primes[j]]=1;
if(i%primes[j]==0)
break;
}
}
return;
}
void Decompose(){
rep(i,1,N){
int x=w[i];
rep(j,1,cnt){
if(x%primes[j]==0){
ans=1;
x/=primes[j];
f[i][++f[i][0]]=primes[j];
while(x%primes[j]==0)
x/=primes[j];
}
if(primes[j]*primes[j]>x)
break;
}
if(x>1)
f[i][++f[i][0]]=x,ans=1;
}
return;
}
void DFS(int x){
vis[x]=1;
rep(i,1,f[x][0])
d[x][i]=1;
for(int p=first[x];p;p=e[p].next){
int y=e[p].to;
if(vis[y])
continue;
DFS(y);
rep(i,1,f[x][0]){
po=lower_bound(f[y]+1,f[y]+1+f[y][0],f[x][i])-f[y];
if(f[y][po]==f[x][i]){
ans=max(ans,d[y][po]+d[x][i]);
d[x][i]=max(d[x][i],d[y][po]+1);
}
}
}
return;
}
int main(){
int fr;
int to;
int maxw=0;
Read(N);
rep(i,1,N){
Read(w[i]);
maxw=max(maxw,w[i]);
}
Euler_Sieve(maxw);
Decompose();
rep(i,2,N){
Read(fr);
Read(to);
addedge(fr,to);
addedge(to,fr);
}
DFS(1);
printf("%d\n",ans);
return 0;
}