📜  仅由质数组成的子数组的计数(1)

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

仅由质数组成的子数组的计数

质数是指只能被1和它本身整除的数。给定一个长度为n的数组a,求仅由质数组成的子数组的计数。

解法

我们可以用筛法求出所有质数,并记录它们的下标。然后从左到右扫描数组,对于每个位置i,我们找到它右边最近的一个质数j,并计算以i为起点,j为终点的子数组的数量。

如何找到i右边最近的质数j呢?我们可以利用数组中质数下标的单调递增性质,二分查找即可。

具体实现可以参考下面的示例代码(使用Python):

def count_prime_subarray(a):
    # 求出所有质数的下标
    is_prime = [True] * (max(a) + 1)
    is_prime[0] = is_prime[1] = False
    primes = []
    for i in range(2, len(is_prime)):
        if is_prime[i]:
            primes.append(i)
            for j in range(i*i, len(is_prime), i):
                is_prime[j] = False
    prime_indices = {p: i for i, p in enumerate(primes)}
    
    # 计算子数组数量
    count = 0
    for i in range(len(a)):
        j = bisect_right(primes, a[i]) - 1
        if j >= 0 and primes[j] == a[i]:
            count += 1
        if j < len(primes) - 1 and primes[j+1] < len(a):
            k = primes[j+1]
            count += (k-i) * (len(a)-k)
            
    return count

其中,bisect_right函数是Python标准库中的二分查找函数。我们还需要在代码开头导入它:

from bisect import bisect_right
时间复杂度

算法的时间复杂度为O(nlogn),其中n为数组长度。质数的数量不会超过n/ln(n),因此筛法的时间复杂度为O(nlog(logn))。对于每个位置i,二分查找的时间复杂度为O(log(n/ln(n))),加上计算子数组数量的常数复杂度,总时间复杂度为O(nlogn)。

空间复杂度

算法的空间复杂度为O(n),需要记录所有质数的下标。