这是一些在线竞争的问题,但现在已经结束了,所以我想知道如何实际解决它。
你得到数字n,它有一些(数字4你有1,2,4)除数(1和它本身包括在内)。如果p等于给定数n的所有除数的乘积,则求p的除数。
我试图解决它,但我的解决方案只是优化的蛮力,所以我正在寻找具有数学背景的快速解决方案。
答案 0 :(得分:1)
让我们看一个例子:105
105
有8个除数:
1, 3, 5, 7, 15, 21, 35, 105
除数乘积的除数为105^(d(105) / 2)
。我们可以通过配对每个除数来轻松地看到这一点:
1, 3, 5, 7, 15, 21, 35, 105
a b c d d c b a
=> a*a * b*b * c*c * d*d
意味着我们将105
乘以d(105) / 2
次。
现在让我们看一下105
的主要因素:
3, 5 and 7
我们将在除数的乘积中得到d(105) / 2 = 4
的每一个:
3*3*3*3 * 5*5*5*5 * 7*7*7*7
上述被乘数组合的方式有多少?
5 ways to set 3
5 ways to set 5
5 ways to set 7
5 * 5 * 5 = 125
105
的除数的乘积有125
个除数。
通用公式:
f(n):
d = product(map (\x -> x + 1) prime_counts)
m = d / 2
counts = map (\x -> m * x + 1) prime_counts
return product(counts)
随机示例:
f(63):
d = product([3, 2]) = 6
m = 6 / 2 = 3
counts = map (\x -> m * x + 1) [2, 1] = [7, 4]
return product([7,4]) = 28
63
,1 * 3 * 7 * 9 * 21 * 63 = 250047
的除数的乘积有28
个除数。
答案 1 :(得分:0)
我认为这项任务基于以下事实:
如果某个数字A
被分解为P1^N1*P2^N2*...*Pk^Nk
,那么A
的除数总数为(N1+1)*(N2+1)*...*(Nk+1)
。很容易理解为什么这是真的:每个素数除数Pi
可以有0
到Ni
的任何幂。
如果D
是除A
而非A/D
的除数,则除数为A
所以你开始分解n
并计算其除数的总数 - 让我们称之为T
。同样重要的是要检查n
是否是完美的正方形(即它的所有Ni
是否均匀)。
现在,如果您的因子分类为n
,则需要对p
进行分解。显然,所有主要因素都是相同的,只有权力会有所不同。您可以根据事实#1和#2计算权力。如果您将n
的所有除数分组成对D
+ n/D
,您可以注意到乘法后的每对除数都会产生n
。唯一的例外情况可能是,如果n
是一个完美的正方形,然后是sqrt(n)
= n/sqrt(n)
,那么就没有对。无论如何,您可能会发现p
正好是n^(T/2)
。 (注意:T
只有在Ni
的所有n
均为偶数时才是奇数,即如果n
是完美的正方形。)
所以这意味着为了获得p
的分解能力,你应该将n
的所有分解能力加倍T/2
,然后计算p
的除数总数。再次使用事实#1中的公式。
我希望这个算法中最长的部分应该是n
的分解,这是一个研究得很好的问题。剩下的应该很快。
答案 2 :(得分:0)
这是一种算法。这可能是可以改进的,但这需要更多的时间和思考。
我们假设n = p^e * N
,其中p
是素数,e
(对于"指数")是正整数,{{1 } {}不能被N
整除。 (即p
属于p^e
的规范素数分解。)然后,如果我们说n
有N
因子(c代表"数") ,即c
,其产品为f1, f2, ..., fc
,则P
的因子为
n
然后第一行的产品是 1 * f1, 1 * f2, ... 1 * fc
p * f1, p * f2, ... p * fc
...
p^e * f1, p^e * f2, ... p^e * fc
,它只是1^c * f1 * f2 * ... * fj
。第二行的产品P
为p^c * f1 * f2 * ... * fj
。最后一行的产品p*c * P
仅为(p^(e))^c * f1 * f2 * ... * fj
。如果我们让p^(e*c) * P
为T(e)
三角形数字,即e
,那么1 + 2 + ... + e
所有这些因素的乘积就是
n
计算p^(c * T(e)) * P^(e+1)
的快捷方式是T(e)
。计算e * (e+1) / 2
的快捷方式是在c
所谓N
的素数因子分类中使用e1, ..., ek
及其指数N
的所有素因子。这两个捷径在数论中是众所周知的。
所以这是一个伪代码算法。
c = (e1 + 1) * ... * (ek + 1)
我在Python 3.6中编写了一个函数来测试算法,最多检查# Find the prime factorization of the product of the factors of n
c = 1
set factor-list and exponent-list to empty lists
for each prime factor p of n:
# Update the prime factorization of the product of factors
e = the exponent of p in the prime factorization of n
multiply each exponent in the exponent-list by e + 1
append p to the factor list
T = e * (e+1) / 2 # the e'th triangular number
append c * T to the exponent-list
# Update the number of divisors of the current product of factors
c = c * (e+1)
# Find the number of divisors of the final product
result = 1
for each x in the exponent-list:
result = result * (x + 1)
return result
。 (该值很低,因为检查函数比我正在检查的函数慢得多。)算法略有改变,找到n = 10000
的下一个素数除数的代码比较简单但速度慢于必要。
n
我的机器上def cnt_divisors_of_prod_of_divisors(n):
"""Return the count of the divisors of the product of the divisors
of n
"""
# Find the prime factorization of the product of the divisors of n
num = n # number to find prime factorization
cnt = 1 # number of divisors of prime-factorization of n already done
divisors = [] # prime divisors of product of divisors of n
exponents = [] # their exponents in the product of divisors of n
p = 1 # a fake prime divisor of n
while num > 1:
# Find the next prime divisor of n
p += 1
while num % p:
p += 1
# Find the exponent of that prime divisor
e = 1
num = num // p
while num % p == 0:
e += 1
num = num // p
# Multiply each exponent in the exponent-list by e + 1
for j in range(len(exponents)):
exponents[j] *= e + 1
# Append p to the divisor list
divisors.append(p)
# Append the new exponent of p in the product to the exponent-list
T = e * (e+1) // 2 # e'th triangular number
exponents.append(cnt * T)
# Update the number of divisors of n
cnt *= e + 1
# Find the number of divisors of the final product
result = 1
for x in exponents:
result *= x + 1
return result
的代码需要6.03微秒,但这个时间在很大程度上取决于n = 10**7
的值。这似乎是可以接受的!