【发布时间】:2020-07-02 14:07:56
【问题描述】:
我正在寻找一种算法,它可以根据已经分解的数字分解数字。换句话说,我正在寻找一种快速算法来将所有数字分解为给定数字,并将它们存储在一个(我猜这是最容易使用的数据结构)列表/元组中。我正在寻找一种“最多 n”的算法,因为我需要最多为“n”的所有数字,而且我想这比逐个检查要快。
对于我正在运行的程序,我希望该算法在合理的时间内(不到一小时)工作 2*10^8。我在python中尝试了一种更天真的方法,首先找到所有素数到“n”,然后对于每个数字“k”,通过检查每个素数直到一个素数除以它(我们称之为p),找到它的素数分解,那么它的因式分解就是k/p + p的因式分解。
from math import *
max=1000000 # We will check all numbers up to this number,
lst = [True] * (max - 2) # This is an algorithm I found online that will make the "PRIMES" list all the primes up to "max", very efficent
for i in range(2, int(sqrt(max) + 1)):
if lst[i - 2]:
for j in range(i ** 2, max, i):
lst[j - 2] = False
PRIMES = tuple([m + 2 for m in range(len(lst)) if lst[m]]) # (all primes up to "max")
FACTORS = [(0,),(1,)] #This will be a list of tuples where FACTORS[i] = the prime factors of i
for c in range(2,max): #check all numbers until max
if c in PRIMES:
FACTORS.append((c,)) #If it's a prime just add it in
else: #if it's not a prime...
i=0
while PRIMES[i]<= c: #Run through all primes until you find one that divides it,
if c%PRIMES[i] ==0:
FACTORS.append(FACTORS[c//PRIMES[i]] + (PRIMES[i],)) #If it does, add the prime with the factors of the division
break
i+=1
在测试中,绝大多数时间都浪费在了检查候选人是否为素数之后的 else 部分。这需要超过我们的 for max = 200000000
附注- 我用这个做什么 - 不重要
我正在运行的程序是找到最小的“n”,使得对于某个“a”,使得 (2n)!/((n+a)!^2) 是一个整数。基本上,我定义了 a_n = 最小 k 使得 (2k)!/((k+n)!^2) 是一个整数。结果,a_1 = 0,a_2 = 208,a_3 = 3475,a_4 = 8174,a_5 = 252965,a_6 = 3648835,a_7 = 72286092。顺便说一句,我注意到 a_n + n 是无平方的,虽然无法证明数学上。使用勒让德公式:https://en.wikipedia.org/wiki/Legendre%27s_formula,我写了这段代码:
from math import *
from bisect import bisect_right
max=100000000 # We will check all numbers up to this number,
lst = [True] * (max - 2) # This is an algorithm I found online that will make the "PRIMES" list all the primes up to "max", very efficent
for i in range(2, int(sqrt(max) + 1)):
if lst[i - 2]:
for j in range(i ** 2, max, i):
lst[j - 2] = False
PRIMES = tuple([m + 2 for m in range(len(lst)) if lst[m]]) # (all primes up to "max")
print("START")
def v(p,m):
return sum([ (floor(m/(p**i))) for i in range(1,1+ceil(log(m,p)))]) #This checks for the max power of prime p, so that p**(v(p,m)) divides factorial(m)
def check(a,n): #This function checks if a number n competes the criteria for a certain a
if PRIMES[bisect_right(PRIMES, n)]<= n + a: #First, it is obvious that if there is a prime between n+1 and n+a the criteria isn't met
return False
i=0
while PRIMES[i] <= n: #We will run through the primes smaller than n... THIS IS THE ROOM FOR IMPROVEMENT - instead of checking all the primes, check all primes that divide (n+1),(n+2),...,(n+a)
if v(PRIMES[i],2*n)<2*v(PRIMES[i],n+a): # If any prime divides the denominator more than the numerator, the fraction is obviously not a whole number
return False
i+=1
return True #If for all primes less than n, the numerator has a bigger max power of p than the denominator, the fraction is a whole number.
#Next, is a code that will just make sure that the program runs all numbers in order, and won't repeat anything.
start = 0 #start checking from this value
for a in range(1,20): #check for these values of a.
j=start
while not check(a,j):
if j%100000==0:
print("LOADING ", j) #just so i know how far the program has gotten.
j+=1
print("a-",a," ",j) #We found a number. great. print the result.
start=j #start from this value again, because the check obviously won't work for smaller values with a higher "a"
【问题讨论】:
标签: python algorithm prime-factoring