首页 > 试题广场 >

小红的树上路径

[编程题]小红的树上路径
  • 热度指数:85 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
小红拿到了一棵树,每个节点有一个点权。她想取一个长度为 2 的路径,将路径上三个节点的权值相乘。小红希望最终三个节点的乘积的因子数量不小于k,请你帮小红求出有多少种选择路径的方案。

输入描述:
第一行输入两个正整数nk,代表节点的数量、路径乘积的因子限制。
第二行输入n个正整数a_i,代表每个节点的权值。
接下来的n-1行,每行输入两个正整数u,v,代表节点u和节点v有一条边连接。

1\leq n \leq 10^5
1\leq k \leq 10^2
1\leq a_i \leq 100
1\leq u,v \leq n


输出描述:
一个整数,代表符合条件的路径方案数。
示例1

输入

4 8
1 2 3 6
1 2
2 3
3 4

输出

1

说明

取路径 2-3-4,乘积为 36,共有 9 个因子。符合条件。
#include <iostream>
#include <vector>
#include <cstring>
#include <utility>
using namespace std;

const int MAXN = 1000001;
int div_cnt[MAXN];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    int n, k;
    cin >> n >> k;
    vector<int> a(n+1);
    for (int i=1; i<=n; i++) {
        cin >> a[i];
    }
    vector<vector<int>> graph(n+1);
    for (int i=0; i<n-1; i++) {
        int u, v;
        cin >> u >> v;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }

    memset(div_cnt, 0, sizeof(div_cnt));
    for (int i=1; i<MAXN; i++) {
        for (int j=i; j<MAXN; j+=i) {
            div_cnt[j]++;
        }
    }

    vector<pair<int, int>> lists[101];
    for (int w=1; w<=100; w++) {
        for (int i=1; i<=100; i++) {
            for (int j=i; j<=100; j++) {
                int product = w * i * j;
                if (product < MAXN && div_cnt[product] >= k) {
                    lists[w].emplace_back(i, j);
                }
            }
        }
    }

    long long ans = 0;
    for (int v=1; v<=n; v++) {
        int w_val = a[v];
        int cnt[101] = {0};
        for (int u : graph[v]) {
            int w_u = a[u];
            if (w_u >= 1 && w_u <= 100) {
                cnt[w_u]++;
            }
        }
        long long S_v = 0;
        for (auto &p : lists[w_val]) {
            int i = p.first, j = p.second;
            if (i == j) {
                S_v += (long long) cnt[i] * (cnt[i] - 1) / 2;
            } else {
                S_v += (long long) cnt[i] * cnt[j];
            }
        }
        ans += S_v;
    }

    cout << ans << endl;
    return 0;
}

发表于 2025-08-21 11:29:47 回复(0)