「一本通 5.2 例 3」数字转换
一道被划分在树形dp中的题,虽然好像没什么关系。。。
题目描述
的约数和 (不包括他本身)比他本身小,那么 可以变成 , 也可以变成 。例如 可以变为 , 可以变为 。限定所有数字变换在不超过
输入格式
输出格式
样例
数据范围与提示
的数据, 。
先预处理建边,(注意加优化,防止超时)然后就成了找树的最大直径,先dfs找一条最长边,在从此点开始dfs
#include<cstdio> #include<iostream> #include<cstring> #include<cmath> using namespace std; const int maxn = 8e4+10; int n,head[maxn],size=0,maxx,ru[maxn],pos=0; bool vis[maxn]; struct edge{ int v,nex; }e[maxn<<1]; void adde(int u,int v){ e[size].v=v;e[size].nex=head[u];head[u]=size++; } void dfs(int u,int dep){ vis[u]=1; if(ru[u]==1){ if(dep>maxx) maxx=dep,pos=u; } for(int i=head[u];~i;i=e[i].nex){ int v=e[i].v;if(vis[v]) continue; dfs(v,dep+1); } } int main(){ memset(head,-1,sizeof(head)); scanf("%d",&n); for(int i=2;i<=n;i++){ int tt=1; for(int j=2;j*j<=i;j++) if(i%j==0) tt+=j+i/j;//优化,这样就不用一直枚举到i if((int)sqrt(i)*(int)sqrt(i)==i) tt-=(int) sqrt(i);//特判 if(tt>=i) continue; adde(i,tt);adde(tt,i);ru[i]++;ru[tt]++; } dfs(1,0); memset(vis,0,sizeof(vis)); maxx=0; dfs(pos,0);//两次dfs printf("%d",maxx); return 0; }