1075. 數字轉換(樹的最長路徑 應用)

數字轉換

如果一個數 x 的約數之和 y(不包括他本身)比他本身小,那麼 x 可以變成 y,y 也可以變成 x。

例如,4 可以變爲 3,1 可以變爲 7。

限定所有數字變換在不超過 n 的正整數範圍內進行,求不斷進行數字變換且不出現重複數字的最多變換步數。

輸入格式

輸入一個正整數 n。

輸出格式

輸出不斷進行數字變換且不出現重複數字的最多變換步數。

數據範圍

1≤n≤50000

輸入樣例:

7

輸出樣例:

3

樣例解釋

一種方案爲:4→3→1→7。

分析:每一個x最多向它的約數之和y連一條邊,每一個點x最多有一個父節點,y是x的父節點,則y與x之間的連線會構成一棵樹(y->x,以1爲根節點的樹)

另外,在求解每個x的約數之和y時,可用篩法求解

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 50000+10;
int sum[N];
int head[N],nexts[N*2],ver[N*2],edge[N*2];
int tot,ans;
void add(int x,int y){
    ver[++tot]=y;
    nexts[tot]=head[x],head[x]=tot;
}
int dfs(int x){
    int d1=0,d2=0;
    for(int i=head[x];i;i=nexts[i]){
        int y=ver[i];
        int d=dfs(y)+1;
        if(d>d1){
            d2=d1;
            d1=d;
        }
        else if(d>d2){
            d2=d;
        }
    }
    ans=max(ans,d1+d2);
    return d1;
}
int main(){
    int n;
    scanf("%d",&n);

    for(int i=1;i<=n;i++){
    //j從2開始循環,所以sum[i]不會加上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);
        }
    }
    dfs(1);
    printf("%d",ans);
    return 0;
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章