如果乙個數x
xx的約數之和y
yy(不包括他本身)比他本身小,那麼x
xx可以變成y
yy,y
yy也可以變成x
xx。例如,4
44可以變為3
33,1
11可以變為7
77。限定所有數字變換在不超過n
nn的正整數範圍內進行,求不斷進行數字變換且不出現重複數字的最多變換步數。
輸入格式:
輸入乙個正整數nnn。
輸出格式:
輸出不斷進行數字變換且不出現重複數字的最多變換步數。
資料範圍:
1 ≤n
≤50000
1≤n≤50000
1≤n≤50
000
設s (x
)=∑d
∣x,1
≤d≤x
ds(x)=\sum_ d
s(x)=∑
d∣x,
1≤d≤
xd,也就是說當y=s
(x
)<
xy=s(x)y=
s(x)
<
x,那麼x
xx和y
yy可以相互轉化。我們考慮一下互相轉化的數所構成的圖有什麼性質。如果y
y< x,那麼有可能有另乙個數z zz,也滿足y=s (z )y=s(z) y=s(z) ,這樣y yy和z zz也能相互轉化,但是比x xx小的且能與x xx互相轉化的數是唯一的,就是s(x )s(x) s(x) 。所以我們可以構造乙個從s(x )→ xs(x)\to x s(x)→x 的有向邊,這樣所有轉化關係形成的圖就是個森林,每棵樹是個有根樹。問題就轉化為了求樹中的最長路徑的長度是多少,參考**如下:#include
#include
using
namespace std;
const
int n =
50010
, m =
2* n;
int n;
int h[n]
, e[m]
, ne[m]
, idx;
int sum[n]
;// 存每個節點是否是樹根,避免重複列舉森林中的樹
bool is_root[n]
;int res;
void
add(
int a,
int b)
intdfs
(int u)
res =
max(res, d1 + d2)
;return d1;
}int
main()
for(
int i =
1; i <= n; i++)if
(is_root[i]
)dfs
(i);
cout << res << endl;
return0;
}時間複雜度o(n
logn)
o(n\log n)
o(nlogn)
(主要的時間花在了兩重迴圈上,n(∑
k=2n
1k)=
o(
nlogn
)n(\sum_^\frac)=o(n\log n)
n(∑k=2
nk1
)=o
(nlogn
)),空間o(n
)o(n)
o(n)
。
AcWing 1075 數字轉換
題目描述 如果乙個數 x 的約數之和 y 不包括他本身 比他本身小,那麼 x 可以變成 y,y 也可以變成 x。例如,4 可以變為 3,1可以變為 7。限定所有數字變換在不超過 n 的正整數範圍內進行,求不斷進行數字變換且不出現重複數字的最多變換步數。輸入格式 輸入乙個正整數 n。輸出格式 輸出不斷...
acwing 1075 數字轉換 (樹形DP)
首先,對於小於n的每個數,我們可以確定它的約數之和 不包括自己 是固定的,就像4的約數之和一定是3,不可能是其他的,那麼我們就可以將2 n的每個數的約數之和求出sum i 對於sum i i 的邊 因為對於每個i,sum i 是唯一確定的 也就是說每個兒子都有唯一乙個父節點,那麼我們最終就會構成森林...
AcWing1075 數字轉換 樹形DP 題解
題目傳送門 如果乙個數 x 的約數之和 y 不包括他本身 比他本身小,那麼 x 可以變成 y,y 也可以變成 x。例如,4 可以變為 3,1 可以變為 7。限定所有數字變換在不超過 n 的正整數範圍內進行,求不斷進行數字變換且不出現重複數字的最多變換步數。輸入格式 輸入乙個正整數 n。輸出格式 輸出...