📅  最后修改于: 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),需要记录所有质数的下标。