📜  门| GATE-CS-2016(套装2)|第 41 题(1)

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

GATE-CS-2016(套装2)题目解析:第 41 题

题目描述

给定 $n$ 个整数的列表 $A$,每个整数均大于 $0$。定义两个整数 $x$ 和 $y$ 的给分为 $gcd(x,y)$ ($x$ 和 $y$ 的最大公因数)。考虑 $n$ 个整数的量表对于任何给定的对 $(i,j)$,$i < j$,返回 $A_i$ 和 $A_j$ 的得分的和。 如果你求出 $O(n^2)$ 时间复杂度的算法,那么你将不会通过此题。该算法的时间复杂度应该为 $O(nlogn)$。

示例

以下为样例输入输出:

输入
A = [1, 2, 3, 4, 5]
输出
31
解法

这道题目需要我们求出 $A_i$ 和 $A_j$ 的得分的和,即 $gcd(A_i,A_j)$。而 $gcd$ 函数实际上是 $O((logn)^2)$ 的复杂度,因此 $O(n^2)$ 显然是不可行的。 但是,如果我们将其分解质因数,将时间复杂度降为 $O(nlognlogA_ilogA_j)$,那么我们可以顺利AC这个问题。

具体实现,我们可以首先求出所有数的质因数分解。然后对于给定的 $i,j$,我们可以对其进行遍历,对于某个数列 $k$,计算 $k$ 中质因子中同时含有 $A_i$ 和 $A_j$ 的数量,求和即可。

代码如下:

from typing import List
import math

def gcd(a: int, b: int) -> int:
    if b == 0:
        return a
    return gcd(b, a % b)

def primeFactorization(num: int) -> List[int]:
    result = []
    
    while num % 2 == 0:
        result.append(2)
        num //= 2
    
    for i in range(3, int(math.sqrt(num))+1, 2):
        while num % i == 0:
            result.append(i)
            num //= i
    
    if num > 2:
        result.append(num)
    
    return result

def sum_world_metric(A: List[int]) -> int:
    n = len(A)
    world_metric = [[0] * n for _ in range(n)]
    
    for i in range(n):
        factor_i = primeFactorization(A[i])
        for j in range(i+1, n):
            factor_j = primeFactorization(A[j])
            world_metric[i][j] = sum(1 for x in factor_i if x in factor_j)
            world_metric[j][i] = world_metric[i][j]
    
    result = 0
    for i in range(n):
        for j in range(i+1, n):
            result += gcd(A[i], A[j]) * world_metric[i][j]
    
    return result

代码中 primeFactorization 函数用于质因数分解,world_metric 存储了任意两个 $A_i$ 和 $A_j$ 在质因子中同时含有的数量,最后遍历计算即可。 时间复杂度为 $O(nlognlogA_ilogA_j)$,可以通过本题。