为什么此代码会返回数字因子的总和?
在几个项目Euler问题中,您被要求计算因子的总和作为问题的一部分。在那里的一个论坛上,有人发布了以下Java代码作为查找总和的最佳方式,因为你实际上不需要找到个别因素,只需要找到主要因素(你不需要知道Java,你可以跳到下面的摘要):
public int sumOfDivisors(int n)
{
int prod=1;
for(int k=2;k*k<=n;k++){
int p=1;
while(n%k==0){
p=p*k+1;
n/=k;
}
prod*=p;
}
if(n>1)
prod*=1+n;
return prod;
}
现在,我已经尝试了很多次,我发现它有效。问题是,为什么?
说出因素100
:1,2,4,5,10,20,25,50,100
。总和为217
。主要因子分解为2*2*5*5
。此功能为您提供[5*(5+1)+1]*[2*(2+1)+1] = [25+5+1]*[4+2+1] = 217
保理8
:1,2,4,8
。总和为15
。主要因子分解为2*2*2
。此功能为您提供[2*(2*(2+1)+1)+1]=15
算法归结为(使用Fi
表示因子F或F sub i的第i个索引):
return product(sum(Fi^k, k from 0 to Ni), i from 1 to m)
其中m
是唯一素因子的数量,Ni
是每个唯一因子在素数因子分解中出现的次数。
为什么这个公式等于因子的总和?我的猜测是,它等于通过分配属性的每个独特的素因子组合(即每个独特因子)的总和,但我不知道如何。
答案 0 :(得分:7)
让我们看看最简单的情况:当 n 是素数的幂时。
k^m
的因子是1,k,k ^ 2,k ^ 3 ... k ^ m-1。
现在让我们看一下算法的内部循环:
第一次迭代后,我们有k + 1
。
第二次迭代后,我们有k(k+1) + 1
或k^2 + k + 1
在第三次迭代之后,我们有k^3 + k^2 + k + 1
等等......
对于作为单个素数的幂的数字,它是如何工作的。我可能会坐下来对所有数字进行概括,但你可能想先自己试一试。
编辑:既然这是已接受的答案,我将通过展示算法如何处理具有两个不同素数因子的数字来详细说明。然后可以直接将其推广到具有任意数量的不同素因子的数字。 x^i.y^j
的因素包括x^0.y^0
,x^0.y^1
... x^0.y^j
,x^1.y^0
......
每个不同素数因子的内部循环生成x^i + x^i-1 + ... + x^0
(类似于y
)。然后我们将它们相乘,我们得到了各种因素。
答案 1 :(得分:0)
算法基本上是查看n的素因子的所有有序子集的集合,这类似于n的因子集。