1577:【例 3】數位轉換
問題描述
如果一個數 x 的約數和 y (不包括他本身)比他本身小,那麼 x 可以變成 y,y 也可以變成 x。例如 4 可以變為 3,1 可以變為 7。限定所有數位變換在不超過 n 的正整數範圍內進行,求不斷進行數位變換且不出現重複數位的最多變換步數。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <queue>
#include <map>
/* #include <unordered_map> */
#include <bitset>
#include <vector>
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define db double
#define Pir pair<int, int>
#define m_p make_pair
#define INF 0x3f3f3f3f
#define esp 1e-7
#define for_(i, s, e) for(int i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(int i = (ll)(e); i >= (ll)(s); i --)
#define sc scanf
#define pr printf
#define sd(a) scanf("%d", &a)
#define ss(a) scanf("%s", a)
#define size() size() * 1LL
#define mod (ll)(10007)
#define Min(a, b, c) min(a, min(b, c))
#define Max(a, b, c) max(a, max(b, c))
using namespace std;
const int mxn = 50005;
vector<int> e[mxn];
int sov(int x)
{
int sum = 0;
for(int i = 1; i * i <= x; i ++)
{
if(x % i) continue;
sum += i;
if(x / i != i && i != 1)
sum += x / i;
}
return sum;
}
Pir a, b;
int dep[mxn];
void dfs(int u, int p, int dep[], Pir & c)
{
dep[u] = dep[p] + 1;
if(c.se < dep[u])
{
c.se = dep[u];
c.fi = u;
}
for_(i, 0, e[u].size() - 1)
{
int v = e[u][i];
if(v == p) continue;
dfs(v, u, dep, c);
}
}
int main()
{
/* fre(); */
int n; sd(n);
for_(i, 2, n)
{
int sm = sov(i);
if(sm < i)
{
e[i].pb(sm);
e[sm].pb(i);
}
}
dfs(1, 0, dep, a);
memset(dep, 0, sizeof(dep));
dfs(a.fi, 0, dep, b);
pr("%d\n", b.se - 1);
return 0;
}
對於這種解法,我只需要弄懂它的狀態轉移方程,就好說了,
定義:dp [mxn][3],
當u ==2時
)在上面這個圖中,子節點 2 能產生最大距離(產生樹的直徑距離)的話,產生的方式有兩種:
在這兩個方案中的 去最大值就可可以得到經過 2 節點路徑的最大長度,如果我們樹中所有的節點所能產生的最大值去最優值,那麼這個最優值就是樹的直徑了,
對於求解 樹中每一個節點 u 的 dp [u][0]、dp [u][1] 的話 我們用一個 dfs 就可以直接求出來了,
但是對於 dp [u][2] 的求法思路是:我在另一個 dfs 函數中,在從上往下遞迴的時候我們利用 當前遞迴的到的節點 u 的 dp [u][0~2] 之間的資料來更新的它的所有子節點的 dp [v][2] 的值,例如在這個圖中如果我們 dfs 到了節點 2,現在要更新它的子節點 4 的 dp [4][2] 的值,
沒有
經過了要更新的節點 4,那麼 dp [4][2] 的的值 = max(紅色線段長度(dp [2][0]) ,紫色線段長度 (dp [2][2]))+ (2-4 這條邊之間的長度),這種解法的思路就是這樣,具體實現看程式碼。。。。。。。。。。。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <queue>
#include <map>
/* #include <unordered_map> */
#include <bitset>
#include <vector>
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define db double
#define Pir pair<int, int>
#define m_p make_pair
#define INF 0x3f3f3f3f
#define esp 1e-7
#define for_(i, s, e) for(int i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(int i = (ll)(e); i >= (ll)(s); i --)
#define sc scanf
#define pr printf
#define sd(a) scanf("%d", &a)
#define ss(a) scanf("%s", a)
#define size() size() * 1LL
#define mod (ll)(10007)
#define Min(a, b, c) min(a, min(b, c))
#define Max(a, b, c) max(a, max(b, c))
using namespace std;
const int mxn = 50005;
vector<int> e[mxn];
int sov(int x)
{
int sum = 0;
for(int i = 1; i * i <= x; i ++)
{
if(x % i) continue;
sum += i;
if(x / i != i && i != 1)
sum += x / i;
}
return sum;
}
int dis[mxn][3];
int mxson[mxn];
void dfs(int u, int p)
{
for_(i, 0, e[u].size() - 1)
{
int v = e[u][i];
if(v == p) continue;
dfs(v, u);
int d = dis[v][0] + 1;
if(d >= dis[u][0])
{
dis[u][1] = dis[u][0];
dis[u][0] = d;
mxson[u] = v;
}
else if(d > dis[u][1])
dis[u][1] = d;
}
}
void dfs2(int u, int p)
{
for_(i, 0, e[u].size() - 1)
{
int v = e[u][i];
if(v == p) continue;
if(mxson[u] != v)
dis[v][2] = max(dis[u][0], dis[u][2]) + 1;
else
dis[v][2] = max(dis[u][1], dis[u][2]) + 1;
dfs2(v, u);
}
}
int main()
{
/* fre(); */
int n; sd(n);
for_(i, 2, n)
{
int sm = sov(i);
if(sm < i)
{
e[i].pb(sm);
e[sm].pb(i);
}
}
dfs(1, 0);
dfs2(1, 0);
int mx = 0;
for_(i, 1, n)
{
mx = Max(mx, dis[i][0], dis[i][2]);
}
pr("%d\n", max(mx, 0));
return 0;
}