数字转换
数字转换
时间限制: 1 Sec 内存限制: 512 MB
题目描述
如果一个数x的约数和y(不包括他本身)比他本身小,那么x可以变成y,y也可以变成x。例如4可以变为3,1可以变为7。限定所有数字变换在不超过n的正整数范围内进行,求不断进行数字变换且不出现重复数字的最多变换步数。
输入
输入一个正整数n。
输出
输出不断进行数字变换且不出现重复数字的最多变换步数。
样例输入
7
样例输出
3
提示
一种方案为4->3->1->7。
对于100%的数据,1<=n<=50000。
对于100%的数据,1<=n<=50000。
这道题首先要求一下从一到n所有数的约数和,如果小于n的话就建边,然后求这棵树的直径就好了。
而树的直径可以用两遍dfs来找,第一遍找到离根节点最远的点,第二遍以离根节点最远的点为起点找离它最远的点,
则这个最远的距离即是直径。
下面是代码:
#include<bits/stdc++.h> using namespace std; int head[200010],to[200010],nxt[200010],tot = 1,n; int max_n,p,q,fa[200010],vis[200010],ans,sum,f[200010]; void add(int x,int y) { to[tot] = y; nxt[tot] = head[x]; head[x] = tot++; } int ys(int x) { int sum=0; for(int i=1;i*i<=x;i++) { if(x%i==0) { sum+=i,sum+=(x/i); if(i*i==x) sum-=i; } } sum-=x; return sum; } void dfs1(int u,int fa_,int len) { if(len>max_n) { max_n=len; p=u; } for (int i=head[u];i;i=nxt[i]) { int v=to[i]; if(v==fa_) continue; dfs1(v,u,len+1); } } void dfs2(int u,int fa_,int len) { if(len>max_n) { max_n=len; q=u; } fa[u]=fa_; for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(v==fa_) continue; dfs2(v,u,len+1); } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { int xx=ys(i); if(xx>=i) continue; add(i,xx); add(xx,i); } dfs1(1,0,0); max_n=0; dfs2(p,0,0); printf("%d",max_n); return 0; }