📅  最后修改于: 2023-12-03 15:12:05.271000             🧑  作者: Mango
给定一个区间 $[L, R]$ 和一个参数 $k$,请计算出该区间内所有不能被前 $k$ 个素数整除的整数的个数。
首先,我们需要求出前 $k$ 个素数,可以使用筛法求素数的方法。
对于每个整数 $x\in[L, R]$,我们枚举前 $k$ 个素数 $p_i$,如果 $x$ 能被 $p_i$ 整除,则不符合条件。因此,我们只需要统计出有多少个数不能被前 $k$ 个素数整除即可。
具体地,假设前 $k$ 个素数分别为 $p_1, p_2, \cdots, p_k$,则区间 $[L, R]$ 内不能被这些素数整除的整数个数等于:
$$(R-L+1)-\sum\limits_{i=1}^k\lfloor\dfrac{R}{p_i}\rfloor+\sum\limits_{1\le i<j\le k}\lfloor\dfrac{R}{p_i p_j}\rfloor-\sum\limits_{1\le i<j<k\le k}\lfloor\dfrac{R}{p_i p_j p_k}\rfloor+\cdots+(-1)^k\lfloor\dfrac{R}{p_1 p_2 \cdots p_k}\rfloor$$
其中 $\lfloor x\rfloor$ 表示下取整函数。
from math import sqrt
def count(L: int, R: int, k: int) -> int:
primes = [] # 存储前 k 个素数
is_prime = [True] * (R + 1)
for i in range(2, R + 1):
if is_prime[i]:
primes.append(i)
if len(primes) == k:
break
for j in range(i * i, R + 1, i):
is_prime[j] = False
ans = R - L + 1
for mask in range(1, 1 << k):
prod = 1
cnt = 0
for i in range(k):
if mask & (1 << i):
prod *= primes[i]
cnt += 1
if cnt % 2 == 0:
ans += (R // prod - (L - 1) // prod)
else:
ans -= (R // prod - (L - 1) // prod)
return ans
L, R, k = map(int, input().split())
print(count(L, R, k))
代码说明:
primes
中;求解前 $k$ 个素数的时间复杂度为 $O(R\log{\log{R}})$,枚举所有子集的时间复杂度为 $O(2^k)$,计算对应倍数的个数的时间复杂度为 $O(\log{R})$。因此,该算法的时间复杂度为 $O(R\log{\log{R}}+2^k\log{R})$。
空间复杂度为 $O(R)$(用于存储前 $k$ 个素数或者用于筛选素数)。