题目描述
如果一个数 x 的约数和 y (不包括他本身)比他本身小,那么 x 可以变成 y,y 也可以变成 x。例如 4 可以变为 3,1 可以变为 7。限定所有数字变换在不超过 n 的正整数范围内进行,求不断进行数字变换且不出现重复数字的最多变换步数。
题意
题目描述有点绕,就是如果x > x的不包括x本身的约数和,
那么 x 和 y 就可以相互转换
思路
把图画出来,你会发现这是一棵树,要你求出树的直径也就是树的最长路径,把每个点的约数和预处理一下就行.
这题应该是只有一棵树的,要不然就是 一本通数据水了 ,或者所有答案都过1这个点所在的树,如果有多个树,对每课树求一下最大路径取最大值就行了
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 5e4 + 10;
const int M = N << 1;
int f[N];
int ans = 0,cnt = 0,n;
int h[N],to[M],w[M],ne[M];
void get_f(int n){
for(int i = 1; i <= n; ++i)
for(int j = i << 1; j <= n; j += i)
f[j] += i;
}
void add(int x, int y, int z){
to[++cnt] = y, w[cnt] = z, ne[cnt] = h[x], h[x] = cnt;
}
int dfs(int u,int fa){
int d,d1,d2,d3;
d = d1 = d2 = d3 = 0;
for( int i = h[u]; ~i ; i = ne[i]){
int x = to[i];
if(x == fa || x > n)
continue;
d = dfs(x,u) + w[i];
if(d >= d1) d2 = d1, d1 = d;
else if(d > d2) d2 = d;
d3 = max(d,d3);
}
ans = max(ans,d1 + d2);
return d3;
}
int main(){
memset( h, - 1 , sizeof h);
cin >> n;
get_f(n);
for(int i = 2; i <= n; ++i){
if(f[i] < i)
{
add(i,f[i],1);
add(f[i],i,1);
}
}
dfs(1,-1);
cout << ans ;
//system("pause");
return 0;
}