首先,我们需要构造一棵树,使得其中有k个节点的权值为2,n-k个节点的权值为3。

我们可以将k个节点的权值为2的节点放在一条链上,然后再将n-k个节点的权值为3的节点依次连接到链的末端。

例如,当n=5,k=2时,我们可以构造如下的树:

  1
 / \
2   3

/
3 3

接下来,我们需要计算每条路径的权值乘积。路径的权值乘积等于路径上所有点权值的乘积的因子数量。

我们可以使用动态规划来计算路径的权值乘积。假设dp[i][j]表示以节点i为根节点的子树中,路径权值乘积为j的路径数量。

我们可以根据节点的权值来更新dp数组。如果节点i的权值为2,那么它的子树中的路径权值乘积为j的路径数量应该等于dp[i的左子节点][j/2] * dp[i的右子节点][j/2]。如果节点i的权值为3,那么它的子树中的路径权值乘积为j的路径数量应该等于dp[i的左子节点][j/3] * dp[i的右子节点][j/3]。

最后,我们可以通过遍历dp[n][j],其中j大于等于1,来找到最小的路径权值乘积。

具体实现时,我们可以使用一个二维数组dp来保存dp数组的值。dp[i][j]表示以节点i为根节点的子树中,路径权值乘积为j的路径数量。初始时,将dp数组中的所有元素都置为0。

然后,我们可以使用深度优先搜索来遍历树中的每个节点。对于节点i,如果它是叶子节点,那么dp[i][2]的值应该为1,dp[i][3]的值应该为1;如果它是非叶子节点,那么根据节点的权值,更新dp[i]数组的值。

最后,我们可以遍历dp[n][j],其中j大于等于1,找到最小的路径权值乘积。答案对10^9+7取模,即答案%=(int)(1e9+7)。

以下是具体的实现代码:

#include <iostream>
#include <vector>
using namespace std;

const int mod = 1e9 + 7;

void dfs(int u, vector<int>& weight, vector<vector<int>>& adj, vector<vector<int>>& dp) {
    if (adj[u].empty()) {
        dp[u][2] = 1;
        dp[u][3] = 1;
        return;
    }
    for (int v : adj[u]) {
        dfs(v, weight, adj, dp);
    }
    if (weight[u] == 2) {
        for (int i = 1; i < dp[u].size(); i++) {
            for (int j = 1; i * j < dp[u].size(); j++) {
                dp[u][i * j] = (dp[u][i * j] + (long long)dp[u][i] * dp[u][j]) % mod;
            }
        }
    } else if (weight[u] == 3) {
        for (int i = 1; i < dp[u].size(); i++) {
            for (int j = 1; i * j * j < dp[u].size(); j++) {
                dp[u][i * j * j] = (dp[u][i * j * j] + (long long)dp[u][i] * dp[u][j] * dp[u][j]) % mod;
            }
        }
    }
}

int main() {
    int n, k;
    cin >> n >> k;

    vector<int> weight(n + 1);
    for (int i = 1; i <= k; i++) {
        weight[i] = 2;
    }
    for (int i = k + 1; i <= n; i++) {
        weight[i] = 3;
    }

    vector<vector<int>> adj(n + 1);
    for (int i = 2; i <= k; i++) {
        adj[i].push_back(i - 1);
    }
    for (int i = k + 1; i <= n; i++) {
        adj[i].push_back(k);
    }

    vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));
    dfs(n, weight, adj, dp);

    int ans = 0;
    for (int j = 1; j <= n; j++) {
        ans = (ans + dp[n][j]) % mod;
    }

    cout << ans << endl;

    return 0;
}

该算法的时间复杂度为O(n^2),空间复杂度为O(n^2)

链接:httpsacnowcodercomacmcontest62033E来源:牛客网小红想让你构造一棵树共有�n个节点其中有�k个节点权值为2�−�n−k个节点的权值为3。小红定义路径权值为路径上所有点权值乘积的因子数量。只有长度不小于1的路径是有效的u到v、v到u是同一条路径。小红希望所有的路径的权值乘积尽可能小你能帮帮她吗?你不需要输出构造出的树只需要输出最小的权值乘积即可。答案对109+7

原文地址: https://www.cveoy.top/t/topic/ioo8 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录