📅  最后修改于: 2023-12-03 15:28:51.182000             🧑  作者: Mango
本文介绍了如何计算除数为素数的[L,R]范围内的数字总和。这是一个常见的问题,例如在质数分解中,需要计算一个数的素数因子的总和。
我们可以枚举[L,R]内的每个数字x,判断它是否是质数的因子。当且仅当x是质数的因子时,我们将其加入到总和中。为了判断一个数是否是质数,可以使用试除法或者埃拉托斯特尼筛法。
试除法即对于每个数字x,枚举[2, x-1]的每个数y,判断y是否是x的因子。如果找到x的非1和非x本身的因子,那么x就不是质数。
def is_prime(num):
if num < 2: # 0和1不是质数
return False
for i in range(2, num):
if num % i == 0:
return False
return True
def prime_factor_sum(L, R):
res = 0
for x in range(L, R+1):
for y in range(2, x):
if x % y == 0 and is_prime(y):
res += y
break # 因为重复的因子只能算一次,所以找到一个就可以退出了
return res
嵌套循环的时间复杂度是O((R-L)^2),而判断一个数是否是素数的时间复杂度是O(sqrt(x)),所以总的时间复杂度是O((R-L)^2 * sqrt(R))。这个算法在L和R都比较大的情况下,效率非常低下。
埃拉托斯特尼筛法是一种用来求小于等于n的所有质数的方法,在本问题中可以用来优化判断一个数是否是素数的过程。
具体来说,我们可以用一个长度为R的布尔数组is_prime来表示[1, R]内的数字是否是素数。初始化时,将is_prime中所有元素标记为True。
接着我们枚举[2, sqrt(R)]内的每个数字i,如果i是素数,我们就将is_prime中i的倍数(除了i本身)全部标记为False。
最后,我们就可以使用is_prime来快速判断一个数是否是素数了。判断一个数字x是否是素数,只需要判断is_prime[x]是否为True。
def prime_factor_sum(L, R):
res = 0
is_prime = [True] * (R+1)
is_prime[0], is_prime[1] = False, False
for i in range(2, int(R**0.5)+1):
if is_prime[i]: # 如果i是素数,将其倍数全部标记为False
for j in range(i*i, R+1, i):
is_prime[j] = False
for x in range(L, R+1):
for y in range(2, x):
if x % y == 0 and is_prime[y]:
res += y
break
return res
初始化is_prime的时间复杂度是O(R),筛掉每个素数的时间复杂度也是O(R),嵌套循环的时间复杂度是O((R-L)^2),所以总的时间复杂度是O(R + (R-L)^2). 当L和R都很大时,这个算法的效率仍然很低,但是比试除法快很多。