我目前正在尝试解决项目euler问题编号23:
完美数字是一个数字,其正确除数的总和恰好等于数字。例如,28的适当除数之和为1 + 2 + 4 + 7 + 14 = 28,这意味着28是一个完美数。
如果n的适当除数之和小于n,则n被称为不足,如果该和超过n则称为n。
由于12是最小的有限数,1 + 2 + 3 + 4 + 6 = 16,可以写成两个有限数之和的最小数是24.通过数学分析,可以看出所有大于28123的整数可以写成两个数字的总和。然而,即使知道不能表示为两个丰富数字之和的最大数量小于该限制,也不能通过分析进一步降低该上限。
找出所有正整数的总和,这些正整数不能写成两个数字的总和。
但是我的代码没有给出正确的结果,而它似乎完全正常。我计算的数字超过了足够数量吗?
private static void Main()
{
List<int> AbudantNumbers = new List<int>();
long sum = 0;
for (int i = 12; i <= 28123; i++)
{
int abudantNumber = GetProperDivisor(i);
if (abudantNumber > i)
{
AbudantNumbers.Add(i);
}
}
for (int k = 1; k <= 28123; k++)
{
int count = 0;
for (int i = 0; i < AbudantNumbers.Count; i++)
{
count = 0;
if (AbudantNumbers[i] > k)
{
break;
}
for (int j = i; j < AbudantNumbers.Count; j++)
{
if (AbudantNumbers[j] > k)
{
break;
}
if (AbudantNumbers[i] + AbudantNumbers[j] == k)
{
count++;
break;
}
}
}
if (count == 0)
{
sum += k;
}
}
Console.WriteLine(sum);
Console.ReadKey();
}
private static int GetProperDivisor(int input)
{
int sum = 1;
for (int i = 2; i <= input / 2; i++)
{
if (input%i == 0)
{
sum += i;
}
}
return sum;
}
我的结果是:297632990 正确的结果是:4179871
当我的代码中没有明显错误时,差异很大。
我的第二种方法:
for (int k = 1; k <= 28123; k++)
{
var k1 = k;
int count =
(from t1 in AbudantNumbers.TakeWhile(t1 => t1 <= k1) let a = t1 select t1).Count(
t1 => AbudantNumbers.TakeWhile(t => t <= k).Any(t => t1 + t == k));
if (count == 0)
{
sum += k;
}
}
我的想法是得到所有数量小于28123的数字,而不是检查小于28123的所有整数(上面的所有内容都有2个数字的总和),而不是旋转所有数字,最后检查abundantNumber1 + abundantNumber2 == currentNumber
是否{{1}}所以我们打破了循环,因为我们只需要那些没有2个丰富数字的总和。
答案 0 :(得分:0)
当您发现当前数字k
是两个数字a[i] + a[j]
的总和时,您设置count
然后突破循环 - 从内循环中取出j
,即。{/ p>
这意味着您仍然会考虑所有剩余的i
,并为其重置count
。实际上,您只考虑小于或等于k
的最后一个数字。这两个数字的总和不太可能涉及这个数字,因此在大多数情况下,添加数字count == 0
的条件是错误的。
当你发现k == a[i] + a[j]
时,你必须打破两个最内层的循环。 C#似乎没有标记循环,因此最好将内循环重构为一个函数,该函数将大量数字列表和k
作为参数;然后,您可以在满足条件时返回true
。
作为快速但难看的修复,您可以添加
if (count) break;
循环过j
之后。
但是,你的方法非常无效。最好只在所有大量数字上编写两个嵌套循环,然后在它们小于28124时将它们的总和添加到一个集合中。然后添加1到28124之间不在集合中的所有数字。