📌  相关文章
📜  每 K 个集合的第一个元素具有恰好 K 个小于 N 的质因子的连续元素(1)

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

介绍

本题的目标是在给定的整数集(1 ≤ 𝐴[𝑖] ≤ 𝑁)中找到符合以下条件的连续子序列:

  • 子序列包含𝐾个元素;
  • 子序列的第一个元素必须是质数,并且恰好具有𝐾个小于𝑁的质因子。
解题思路

首先可以想到的是进行暴力枚举,即枚举每个可能符合条件的子序列,判断其第一个元素是否为质数,以及是否恰好具有𝐾个小于𝑁的质因子。但此方法时间复杂度为 $𝑂(𝑁^3)$,无法通过本题。

考虑优化暴力枚举方法,将每个可能符合条件的子序列的第一个元素的质因数分解出来,然后记录下每个质因数的出现次数和质因数的种类数。使用滑动窗口来移动子序列,每次移动的时候判断加入和移除的元素的质因数对答案有没有贡献即可。

时间复杂度为 $𝑂(𝐾𝑁log_2(𝑁))$,可以通过本题。具体实现可以参考下方代码。

代码实现
def count_prime_factors(n, primes):
    """
    计算n的质因数分解结果
    """
    res = {}
    for p in primes:
        while n % p == 0:
            if p not in res:
                res[p] = 0
            res[p] += 1
            n //= p
        if n == 1:
            break
    if n > 1:
        if n not in res:
            res[n] = 0
        res[n] += 1
    return res


def solve(N, K):
    # 计算N以内的所有质数
    primes = []
    is_prime = [True] * (N + 1)
    for i in range(2, N + 1):
        if is_prime[i]:
            primes.append(i)
            for j in range(i * i, N + 1, i):
                is_prime[j] = False

    # 计算每个数的质因数分解结果
    A = []
    for i in range(1, N + 1):
        A.append(count_prime_factors(i, primes))

    # 滑动窗口求解
    ans = 0
    cnt = {}
    j = 0
    for i in range(N - K + 1):
        while j < N and len(cnt) < K:
            for p, c in A[j].items():
                if p not in cnt:
                    cnt[p] = 0
                cnt[p] += c
            j += 1
        if len(cnt) == K:
            is_prime = True
            for p in A[i]:
                if cnt.get(p, 0) != A[i][p]:
                    is_prime = False
                    break
            if is_prime:
                ans += 1
        for p, c in A[i].items():
            if cnt[p] == c:
                del cnt[p]
            else:
                cnt[p] -= c

    return ans