思路:
树形dp求最长链。
#include<cstdio> #include<iostream> #include<cstdlib> using namespace std; const int maxn = 100010; void qread(int &x){ x = 0; register int ch = getchar(); while(ch < '0' || ch > '9') ch = getchar(); while(ch >= '0' && ch <= '9') x = 10 * x + ch - 48, ch = getchar(); } int n, rt; int head[maxn]; int go[maxn << 1]; int nxt[maxn << 1]; int d1[maxn]; int d2[maxn]; int f[maxn]; int deep[maxn]; int sum[maxn]; void dfs(int x){ for(int i = head[x]; i; i = nxt[i]) if(!deep[i]){ f[go[i]] = x; deep[go[i]] = deep[x] + 1; dfs(go[i]); } } inline void init(){ qread(n); for(int i=1; i<=n; ++i) for(int j=2; j<=n/i; ++j){ if(i * j > n) break; sum[i * j] += i; } for(int i=1; i<=n; ++i){ if(sum[i] < i){ go[i] = sum[i]; nxt[i] = head[i]; head[i] = i; go[i + n] = i; nxt[i + n] = head[sum[i]]; head[sum[i]] = i + n; } else{ go[i] = 0; nxt[i] = head[i]; head[i] = i; go[i + n] = i; nxt[i + n] = head[0]; head[0] = i + n; } } rt = 0; deep[rt] = 1; dfs(rt); } void DP(int x){ for(int i=head[x]; i; i=nxt[i]){ if(go[i] != f[x]){ DP(go[i]); if(d1[go[i]] + 1 > d1[x]){ d2[x] = d1[x]; d1[x] = d1[go[i]] + 1; } else if(d1[go[i]] + 1 > d2[x]) d2[x] = d1[go[i]] + 1; } } } int main(void){ init(); DP(rt); int ans = 0; for(int i = head[rt]; i; i = nxt[i]) ans = max(ans, d1[go[i]] + d2[go[i]]); printf("%d\n", ans); }