题解:参考 https://www.cnblogs.com/forward777/p/11008262.html
将每个数x和它的因数和y连边,y变为x的父节点,这样建立一颗树,求出树的最长链即可。
具体来说,d1[x]表示最长链的长度,d2[x]表示次长链的长度,y是x的孩子
if(d1[y]+1>d1[x]) d2[x]=d1[x],d1[x]=d1[y]+1;
else d2[x]=max(d2[x],d1[y]+1);
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 50010;
int sum[maxn]; // 约数和
int f1[maxn], f2[maxn]; // 最长链和次长链
int main() {
int n;
scanf("%d", &n);
// 模拟素数筛的方式
for(int i = 1;i <= n;i++)
for(int t = (i<<1);t <= n;t+=i) sum[t] += i;
int ans = 0;
for(int i = n;i >= 1;i--) {
int t = sum[i];
if(t >= i) continue;
if(f1[i]+1 > f1[t]) {
f2[t] = f1[t];
f1[t] = f1[i] + 1;
} else if(f1[i]+1 > f2[t]) {
f2[t] = f1[i] + 1;
}
}
for(int i = 1;i <= n;i++) ans = max(f1[i]+f2[i], ans);
printf("%d\n", ans);
// scanf("%d", &ans);
return 0;
}