如果一个数 xx 的约数之和 yy(不包括他本身)比他本身小,那么 xx 可以变成 yy,yy 也可以变成 xx。
例如,44 可以变为 33,11 可以变为 77。
限定所有数字变换在不超过 nn 的正整数范围内进行,求不断进行数字变换且不出现重复数字的最多变换步数。
输入格式
输入一个正整数 nn。
输出格式
输出不断进行数字变换且不出现重复数字的最多变换步数。
数据范围
1≤n≤500001≤n≤50000
输入样例:
7
输出样例:
3
样例解释
一种方案为:4→3→1→74→3→1→7。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 50010, M = N;
int h[N], e[M], w[M], ne[M], idx;
bool st[N];
int ans;
int sum[N];
int n;
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
int dfs(int u){
st[u] = true;
int dist = 0;
int d1 = 0, d2 = 0;
for (int i = h[u]; ~i; i = ne[i]){
int j = e[i];
if (!st[j]){
int d = dfs(j) + 1;
dist = max(dist, d);
if (d > d1) d2 = d1, d1 = d;
else if (d > d2) d2 = d;
}
}
ans = max(ans, d1 + d2);
return dist;
}
int main(){
scanf("%d", &n);
memset(h, -1, sizeof h);
for (int i = 1; i <= n; i ++)
for (int j = 2; j <= n / i; j ++)
sum[i * j] += i;
for (int i = 2; i <= n; i ++)
if (sum[i] < i) add(sum[i], i);
for (int i = 1; i <= n; i ++)
if (!st[i]) dfs(i);
cout << ans << endl;
return 0;
}