Algorithm 如何计算具有一定除数的最小数?
从 120的除数是16。事实上,120是有16个除数的最小数 找到具有2**500500除数的最小数。给出你的答案,模为500507 计算n的除数非常简单,例如在Python中Algorithm 如何计算具有一定除数的最小数?,algorithm,math,Algorithm,Math,从 120的除数是16。事实上,120是有16个除数的最小数 找到具有2**500500除数的最小数。给出你的答案,模为500507 计算n的除数非常简单,例如在Python中len([i代表i在范围内(1,n+1),如果n%i==0])。这是O(n) 我尝试了暴力搜索,发现32除数的最小数字是840,但对于上面的问题来说,速度太慢了。从不等式count\u除数(n)中,除自身外,任何数字的最大除数都是该数字的一半。例如,120本身以外的最大除数为60。因此,您可以轻松地将范围从(n+1)减小到
len([i代表i在范围内(1,n+1),如果n%i==0])
。这是O(n)
我尝试了暴力搜索,发现32除数的最小数字是840,但对于上面的问题来说,速度太慢了。从不等式
count\u除数(n)中,除自身外,任何数字的最大除数都是该数字的一半。例如,120本身以外的最大除数为60。因此,您可以轻松地将范围从(n+1)减小到(n/2)
此外,对于一个有m个除数的数字,该数字必须至少((m-1)*2)遵循上述逻辑(-1,因为第m个数字本身就是)。例如,具有4个除数的数字必须至少为6。因此,您对n的搜索范围现在变小了
这两种方法将稍微减少运行时间。您应该使用整数的除数n
的公式:
d(n)=(a1+1)(a2+1)…(ak+1)
在哪里
n=p1a1*p2a2*p3a3*…*pkak
是每个整数通过其素因子的幂的唯一表示。这是一个众所周知的公式,但是如果人们想知道如何得到它,请注意,代码> d>代码>将代码< N>代码>如果且仅当代码> d>代码>是p1x1*2x2*p3x3***pkxk的形式,其中席席的每一个都在0和ai之间,所以选择AI的每一个都有AI+ 1的可能性。现在只需应用乘积规则,就可以得到所需的公式
对于固定的d(n)
(与您的情况一样),n
的最小值显然是通过仔细选择现有素数的幂或添加新素数来获得的。让我们看一看这个简单的例子,16:
d(x)=(a1+1)(a2+1)…(ak+1)=16=24
这意味着您最多有4个不同的素数,因此:
x=2a1*3a2*5a3*7a4
其中ai>=0。现在的问题是-为了获得x
的最小值,最好增加2的幂(即增量a1),还是使用7(即取a4=1而不是a4=0)?很容易检查,2*3*5*7>23*3*5=120,这就是为什么在这种情况下120是答案
如何推广这种方法?您应该创建最小堆,在其中放置素数的幂,注意除数的数量达到指定的值。对于16,这个最小堆将包含数字2、3、5、7、22、32、24等。为什么?因为16=24,所以(ai+1)中的每一个都必须除以16,也就是说,它必须是2的幂。每次添加新幂时,它应该将左侧(即变量d(x)
)的幂增加2,因为您的最终目标是找到具有250000除数的最小数。堆用第一个k
素数初始化(在问题语句中,k=500500
),在每个步骤中,当您从堆中弹出px时,返回p2x,并将结果乘以px。d(x)
=16=24的逐步解决方案:
HTH.不完整,请回答一些提示:
n
的最大整数除数为n/2
因此,不需要检查所有小于或等于n
divisors | prime_divisors | non_prime_divisors | LCM(all divisors)
1 | 1 | | 1
2 | 1,2 | | 2
3 | 1,2 | 4 | 4
4 | 1,2,3 | 6 | 6
5 | 1,2 | 4,8,16 | 16
6 | 1,2,3 | 4,6,12 | 12
7 | 1,2 | 4,8,16,32,64 | 64
8 | 1,2,3 | 4,6,8,12,24 | 24
...
16 | 1,2,3,5 |4,6,8,10,12,15,20,24,30,40,60,120 | 120
最大素数因子是sqrt(n)
,因此无需测试n
,而只需测试sqrt(n)
或超过一半n
位的数字
m=(2^(ceil(ceil(log2(n))/2)+1))-1
这应该会加快一些速度,但是你需要增加非素数因子的计算因此,试着找到生成这个顺序的方程,然后简单地计算模算术中的第n次迭代(简单的PI运算…
modmul
)。我可以看到奇偶元素有独立的方程 1: 1
2: 1, 2
3: 1, 2, 4
4: 1, 2, 3, 6
5: 1, 2, 4, 8, 16
6: 1, 2, 3, 4, 6, 12
7: 1, 2, 4, 8, 16, 32, 64
8: 1, 2, 3, 4, 6, 8, 12, 24
9: 1, 2, 3, 4, 6, 9, 12, 18, 36
10: 1, 2, 3, 4, 6, 8, 12, 16, 24, 48
11: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512,1024
12: 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60
13: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512,1024,2048,4096
14: 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 192
15: 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 36, 48, 72, 144
16: 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 24, 30, 40, 60, 120
正如Miljen Mikic解释的那样,除数计数函数是由素因子分解决定的。要计算n,从1开始,使用贪婪算法将除数k倍增加一倍,在每一步选择最便宜的因子。初始成本是素数,使用它们时用它们的平方代替。在预先计算了前k个素数之后,您可以使用最小堆快速完成这项工作。用Python
import primesieve # pip install primesieve
import heapq
def solve(k, modulus=None):
"""Calculate the smallest number with 2**k divisors."""
n = 1
costs = primesieve.generate_n_primes(k) # more than necessary
for i in range(k):
cost = heapq.heappop(costs)
heapq.heappush(costs, cost**2)
n *= cost
if modulus:
n %= modulus
return n
assert solve(4) == 120
if __name__ == "__main__":
print(solve(500500, 500500507))
下面是我的Javascript的高级要点,其中
factorCount
表示除数的数量:
- 找到factorCount的主因子分解
- 生成这些主要因素的每个独特组合
- 对于每个组合,从原始素因子数组中提取这些组合值,并在此数组中添加一个值,即提取的值相乘。然后按降序排列元素
- 对于上一步创建的每个数组,检查在计算2^(b1-1)*3^(b2-1)5^(b3-1)时生成的最小数
- 此计算的最小数是具有
因子数因子计数的最小数
var primeFactors=findPrimeFactors(factorCount);
var primeFactorCombinations=removeduplicatearray(generateCombinations(primeFactors,1));
var CombinedFactorConditions=生成组合因子组合(primeFactors,primeFactorCombinations);
var smallestNumberWithFactorCount=确定最小值(组合因子条件);
下面是完整的沙邦:
函数smallestNumberByFactorCount(factorCount){
函数isPrime(primeCandidate){
var p=2
import primesieve # pip install primesieve
import heapq
def solve(k, modulus=None):
"""Calculate the smallest number with 2**k divisors."""
n = 1
costs = primesieve.generate_n_primes(k) # more than necessary
for i in range(k):
cost = heapq.heappop(costs)
heapq.heappush(costs, cost**2)
n *= cost
if modulus:
n %= modulus
return n
assert solve(4) == 120
if __name__ == "__main__":
print(solve(500500, 500500507))
> smallestNumberByFactorCount(3) --> 4
> smallestNumberByFactorCount(4) --> 6
> smallestNumberByFactorCount(5) --> 16
> smallestNumberByFactorCount(6) --> 12
> smallestNumberByFactorCount(16) --> 120
> smallestNumberByFactorCount(100) --> 45360
> smallestNumberByFactorCount(500) --> 62370000
> smallestNumberByFactorCount(5000) --> 4727833110000
> smallestNumberByFactorCount(100000000) --> 1.795646397225103e+40
def find_smallest_number(num):
number2=0
if(num%8==0):
number2=min(2**((num/4)-1)*3**1*5**1 , 2**((num//2)-1)*3**1)
elif(num%9==0):
number2=2**((num/9)-1)*3**2*5**2
elif(num%2==0 and num%3==0):
number2=2**((num/6)-1)*3**2*5**1
elif((num%4==0)):
number2=2**((num/4)-1)*3**1*5**1
elif(num%2==0):
number2=2**((num/2)-1)*3**1
else:
number2=2**(num-1)
return number2
num=32
print("The number of divisors :",num)
result=find_smallest_number(num)
print("The smallest number having",num," divisors:",result)
def findfactors(num):
list1=[]
for i in range(num,1,-1):
if num%i==0:
list1.append(i)
return list1
def getcombinations(num):
factors=findfactors(num)
list1=[]
if num==1:
return 1
for i in factors:
if getcombinations(num//i)!=1:
list1.append([i,getcombinations(num//i)])
else:
list1.append(i)
return list1
def unloadlist(list1):
list2=[]
if type(list1).__name__=="list":
for i in list1[1]:
if type(i).__name__=="list":
i=unloadlist(i)
if type(i).__name__=="list":
flag=True
for j in i:
if type(j).__name__=="list":
list2.append([list1[0]]+j)
flag=False
if flag==True:
list2.append([list1[0]]+i)
else:
list2.append([list1[0],i])
if len(list2)==1:
list2=list2[0]
else:
list2=list1
return list2
def mergeitems(list1):
list2=[]
for i in list1:
if type(i).__name__=="int":
list2.append((i,))
elif type(i).__name__=="list":
if type(i[0]).__name__!="list":
list2.append(tuple(sorted(i,reverse=True)))
else:
for j in i:
list2.append(tuple(sorted(j,reverse=True)))
set1=set(list2)
return set1
def find_smallest_number(num):
#start writing your code here
list1=getcombinations(num)
for i in range(0,len(list1)):
list1[i]=unloadlist(list1[i])
mainlist=mergeitems(list1)
possibles=[]
primes=[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227]
for i in mainlist:
num=1
for j in range(0,len(i)):
num*=primes[j]**(i[j] - 1)
possibles.append(num)
return min(possibles)
num=7
print("The number of divisors :",num)
result=find_smallest_number(num)
print("The smallest number having",num," divisors:",result)
2**31 * (3...7)**15 * (11...47)**7 * (53...2,713)**3 * (2,719...7,370,029)
Single primes (the last term of the PF) total 499,688.