我写了两个算法来得到给定数字的正确除数的总和,以找到完美的数字或数量。
long sum_divisors_1(int a)
{
int i, t;
long sum = 1;
for (i = 2, t = sqrt(a); i < t + 1; i++) {
if (a % i == 0) {
sum += i;
sum += a / i;
}
}
if (a % t == 0)
sum -= t;
return sum;
}
long sum_divisors_2(int a)
{
int i, sum;
sum = 0;
for (i = 1; i < (int) (a / 2 + 1); i++) {
if (a % i == 0)
sum += i;
}
return sum;
}
我认为它们都是正确的,第一个更快。但我只能从第二个算法得到正确的结果。代码的其他部分是相同的。
有什么建议吗?如何在实际工业规划中找到适当的除数?
提前致谢。
答案 0 :(得分:2)
你的问题在于:
if (a % t == 0)
sum -= t;
由于您将t
从浮点转换为int,因此它将向下舍入为整数值。这也假设 t
是实际的平方根。当数字具有因子x
&amp;时,这将评估为真。 x+1
(我发布的单元测试也在i = 6
时失败,因为它的平方根是2.45而2是一个因子)。
检查确实应该是:
if (t*t == a)
sum -= t;
答案 1 :(得分:1)
这是一个老问题,但我正在浏览。
有一种更快的算法可以找到合适的除数之和。
使用Sieve of Eratosthenes(或Atkin)找出数字的素因子。通过车轮分解,前1米素数可能需要30毫秒。
然后所有除数的总和是
For each n
sum += (n ^ (m+1) - 1) / (n-1)
其中n是因子,m是该因子的幂。
例如220 2 ^ 2 5 11是因素
所以这是
的总和2 ^ (2+1) - 1 / 1 *
5 ^ (1+1) - 1 / 4 *
11 ^ (1+1) - 1 / 10
= 7 * 6 * 12
= 504
这是所有除数的总和,所以只需减去N
504-220 = 284
这比尝试所有数字要快得多,特别是如果你预先计算筛子并重复使用它。
答案 2 :(得分:0)
这是我用C#编写的一个简单的单元测试,它会很快使#1失效,因为#2是正确的:
for(int i = 4; i < 28124; i++)
{
Assert.AreEqual(sum_divisors_2(i), sum_divisors_1(i), "Failed when i = {0}", i);
}
评论太大了......
答案 3 :(得分:0)
Templatetypedef解决了你的问题;然而,计算主要因子的最快方法是使用Eratostene筛子预先计算所有素数因子直至sqrt(MAX_INT),将其存储到数组中然后使用它来分解数字a。这真的非常快。