树形dp(数字转换NOIP17提高模拟训练4)

如果一个数x的约数和(不包括它本身,下同)比它本身小,那么x可以变成它的约数和;如果对于某个y>x且y的约数和为x,那么x也可以变成y。例如,4可以变为3,1可以变为7。限定所有的数字变换在不超过n的正整数范围内进行,求不断进行数字变换且没有重复数字出现的最多变换步数。
输入一个正整数n。
输出最少需要花费的时间。

样例输入:

7

样例输出:

3
这是网上抄来的解析:如果x和y可以互相转化,就连接一条无向边,最后得到的图其实是一个森林,每棵树都是无根树,其实就是要求,整个森林中两个连通的点的最远距离(这里边权都是1),和在无根树中求两点最远距离是一样的,不过这题的特殊性,可以更方便点
对于任意一条边,必有x这是我的代码:
#include
#define maxn 102930
using namespace std;
int n;

long long sum[maxn],m1[maxn],m2[maxn];

void solve()
{
	
	for(int i=n;i>=1;i--)
	{
		if(sum[i]m1[sum[i]])
			{
				m2[sum[i]]=m1[sum[i]];
				m1[sum[i]]=m1[i]+1;
			}
			else if(m1[i]+1>m2[sum[i]])
				m2[sum[i]]=m1[i]+1;
		} 
	}
	long long ans=0;
	for(int i=1;i<=n;i++)
		ans=max(m1[i]+m2[i],ans);
	cout<>n;
   for(int i=1;i<=n;i++) sum[i]=1;
   for(int i=2;i<=n/2;i++)
		for(int j=2*i;j<=n;j+=i)//求约数和 
			sum[j]+=i;
	solve();
   return 0;
}

  



你可能感兴趣的:(树形dp(数字转换NOIP17提高模拟训练4))