📜  树中具有质数总和权重的节点数(1)

📅  最后修改于: 2023-12-03 15:26:41.030000             🧑  作者: Mango

树中具有质数总和权重的节点数

本题旨在求出树中具有质数总和权重的节点数。

问题描述

给定一棵树,树上每个节点有一个权重,权重是该节点到根节点的路径上所有节点权重的和。如果某棵子树的节点权重之和为质数,则称这棵子树具有质数总和权重。

现在要求你编写一个程序,输入树的节点数量 $n$,以及每个节点的权重,输出树中具有质数总和权重的节点数。

输入格式

第一行包含一个整数 $n$,表示树的节点数量。

第二行包含 $n$ 个整数,分别表示每个节点的权重。

接下来 $n-1$ 行,每行包含两个整数 $a$ 和 $b$,表示节点 $a$ 和节点 $b$ 之间存在一条边。

输出格式

一个整数,表示树中具有质数总和权重的节点数。

样例

输入样例:

5
6 7 6 4 1
1 2
1 3
2 4
2 5

输出样例:

2
分析

这道题的主要难点在于如何高效地计算每个节点到根节点的路径上所有节点权重的和,这可以采用树的遍历来实现。

接下来考虑如何判断某个节点所在的子树是否具有质数总和权重。这可以采用质数筛选法来实现,具体过程如下:

  1. 从小于 $n$ 的整数中筛选出所有质数。
  2. 对于树的任意一个非叶子节点,计算其所有子节点的权重之和,如果该和是一个质数,则该节点所在的子树具有质数总和权重。

为了避免重复计算,可以采用记忆化策略将已经计算过的子树的状态保存下来,并将该状态作为递归函数的参数进行传递。

最后,遍历整棵树,统计具有质数总和权重的节点数即可。

算法

计算每个节点的权重以及判断子树是否具有质数总和权重的算法时间复杂度均为 $O(n)$,遍历整棵树的时间复杂度为 $O(n)$,因此总时间复杂度为 $O(n)$。

代码
import math

def is_prime(n):
    """判断给定的数是否为质数"""
    if n <= 1:
        return False
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            return False
    return True

def count_prime_sum_weights(node, weights, memo):
    """计算给定节点子树的权重之和,并判断该子树是否具有质数总和权重"""
    if node in memo:
        return memo[node]

    sum_weight = weights[node - 1]
    is_prime_sum_weight = is_prime(sum_weight)

    for child in tree[node]:
        child_sum_weight, child_is_prime_sum_weight = count_prime_sum_weights(child, weights, memo)
        sum_weight += child_sum_weight
        is_prime_sum_weight |= child_is_prime_sum_weight

    memo[node] = (sum_weight, is_prime_sum_weight)
    return memo[node]

n = int(input().strip())
weights = list(map(int, input().strip().split()))
tree = [[] for _ in range(n + 1)]
for _ in range(n - 1):
    a, b = map(int, input().strip().split())
    tree[a].append(b)
    tree[b].append(a)

memo = {}
answer = 0
for node in range(1, n + 1):
    sum_weight, is_prime_sum_weight = count_prime_sum_weights(node, weights, memo)
    if is_prime_sum_weight:
        answer += 1

print(answer)

其中 is_prime 函数用来判断一个数是否为质数, count_prime_sum_weights 函数用来计算给定节点子树的权重之和,并判断该子树是否具有质数总和权重。函数中的 memo 参数用来保存已经计算过的子树的状态,避免重复计算, node 参数表示要计算的当前节点的编号, weights 参数表示每个节点的权重,函数返回一个元组 (sum_weight, is_prime_sum_weight),其中 sum_weight 是该子树的权重之和,is_prime_sum_weight 表示该子树是否具有质数总和权重。

在主函数中,首先读入树的信息,然后遍历整棵树,对于每个节点,调用 count_prime_sum_weights 函数计算其子树的权重之和和是否具有质数总和权重的状态。如果某个节点的子树具有质数总和权重,则将 answer 加 1。最后输出 answer 即可。