📅  最后修改于: 2023-12-03 15:26:26.386000             🧑  作者: Mango
给定一个整数序列,求它的最长子序列,使得该子序列中任意两个数的最小公倍数(LCM)最小。
def lcm(a, b):
'''
求a,b两个整数的最小公倍数
'''
import math
return a * b // math.gcd(a, b)
def prime_factorization(num):
'''
对整数进行质因数分解,返回一个质因数及其指数的字典
'''
factors = {}
i = 2
while i <= math.sqrt(num):
if num % i == 0:
if i not in factors:
factors[i] = 1
else:
factors[i] += 1
num //= i
i = 2
else:
i += 1
if num > 1:
if num not in factors:
factors[num] = 1
else:
factors[num] += 1
return factors
def get_min_lcm_sequence(arr):
'''
返回整数序列arr的最小LCM的最长子序列
'''
primes = set()
for num in arr:
primes |= set(prime_factorization(num).keys())
primes = sorted(primes)
count_arr = [[prime_factorization(num).get(prime, 0) for num in arr] for prime in primes]
count_arr = list(map(tuple, count_arr))
length = len(primes)
dp = [1] * length
prev = [-1] * length
for i in range(length):
for j in range(i):
if all(count_arr[i][k] >= count_arr[j][k] for k in range(len(count_arr[i]))):
if dp[j] + 1 > dp[i]:
dp[i] = dp[j] + 1
prev[i] = j
max_len_index = max(enumerate(dp), key=lambda x: x[1])[0]
res = []
while max_len_index != -1:
res.append(arr[max_len_index])
max_len_index = prev[max_len_index]
res.reverse()
return res
给定序列 [4, 6, 8, 10, 12, 34, 45, 67, 89]
,最小LCM的最长子序列为 [4, 6, 10, 34, 45]
。
>>> get_min_lcm_sequence([4, 6, 8, 10, 12, 34, 45, 67, 89])
[4, 6, 10, 34, 45]