FF的除数(计算给定数的除数乘积的除数)

时间:2018-01-13 16:22:42

标签: c++ algorithm math

这是一些在线竞争的问题,但现在已经结束了,所以我想知道如何实际解决它。

  

你得到数字n,它有一些(数字4你有1,2,4)除数(1和它本身包括在内)。如果p等于给定数n的所有除数的乘积,则求p的除数。

我试图解决它,但我的解决方案只是优化的蛮力,所以我正在寻找具有数学背景的快速解决方案。

3 个答案:

答案 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

631 * 3 * 7 * 9 * 21 * 63 = 250047的除数的乘积有28个除数。

答案 1 :(得分:0)

我认为这项任务基于以下事实:

  1. 如果某个数字A被分解为P1^N1*P2^N2*...*Pk^Nk,那么A的除数总数为(N1+1)*(N2+1)*...*(Nk+1)。很容易理解为什么这是真的:每个素数除数Pi可以有0Ni的任何幂。

  2. 如果D是除A而非A/D的除数,则除数为A

  3. 所以你开始分解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的规范素数分解。)然后,如果我们说nN因子(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。第二行的产品Pp^c * f1 * f2 * ... * fj。最后一行的产品p*c * P仅为(p^(e))^c * f1 * f2 * ... * fj。如果我们让p^(e*c) * PT(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的值。这似乎是可以接受的!