acwing 1075 digital conversion (tree DP)

Topic

Insert picture description here

answer

  1. First of all, for each number less than n, we can make sure that the sum of its divisors (not including itself) is fixed, just like the sum of the divisors of 4 must be 3, it cannot be other, then we can Calculate sum[i] from the sum of the divisors of each number of 2-n. For sum[i]<i, we connect an edge of sum[i]---->i (because for each i, sum[i] is uniquely determined), which means that each son has a unique parent node, then we will eventually form a forest (multi-class tree), and the longest transformation step in the question will be converted into a tree Longest diameter
  1. Why not start from 1, because the sum of the divisors of 1 is 0 except for itself, and the minimum requirement in the question is 1, so 1 does not meet the requirements
  1. How to find the longest diameter of a tree, we can enumerate each point in turn, find the longest and second longest distances of this point, and then add them together. You can see the longest path of the tree for details. I won’t explain it in detail here.

Code

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 5e4 + 10;

int n;
int h[N], e[N], ne[N], idx;
int sum[N];   //约数之和
bool is[N];   //是否已经用过
int ans;


void add(int a, int b) {
    
    
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}

int dfs(int u) {
    
    

    int d1 = 0, d2 = 0;
    for (int i = h[u]; i != -1; i = ne[i]) {
    
    
        int j = e[i];
        int d = dfs(j) + 1;
        if (d > d1) d2 = d1, d1 = d;
        else if (d > d2) d2 = d;
    }

    ans = max(ans, d1 + d2);

    return d1;
}


int main() {
    
    

    memset(h, -1, sizeof h);

    cin >> n;

    for (int i = 1; i <= n; 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);
        }
        is[i] = true;
    }

    for (int i = 1; i <= n; i++) {
    
    
        if (!is[i]) {
    
       //说明是父节点
            dfs(i);
        }
    }

    cout << ans << endl;

    return 0;
}

Guess you like

Origin blog.csdn.net/qq_44791484/article/details/114745264