非过剩数之和
作者:Shlomi Fish
http://projecteuler.net/problem=23
如果一个数的所有真因数之和等于它本身,则该数被称为完全数。例如,28 的真因数之和为 1 + 2 + 4 + 7 + 14 = 28,这意味着 28 是一个完全数。
如果一个数 n 的所有真因数之和小于 n,则该数被称为亏数;如果该和大于 n,则该数被称为过剩数。
由于 12 是最小的过剩数,1 + 2 + 3 + 4 + 6 = 16,因此可以写成两个过剩数之和的最小数字是 24。通过数学分析,可以证明所有大于 28123 的整数都可以写成两个过剩数之和。然而,即使已知不能表示为两个过剩数之和的最大数小于此上限,但通过分析也无法进一步降低此上限。
求所有不能写成两个过剩数之和的正整数之和。
use v6;
my @divisors_sums;
@divisors_sums[1] = 0;
my $MAX = 28_123;
for (1 .. ($MAX +> 1)) -> $div {
loop (my $prod = ($div +< 1); $prod <= $MAX; $prod += $div) {
@divisors_sums[$prod] += $div;
}
}
# Memoized.
#
my @is_abundant_sum;
my @abundants;
my $total = 0;
for (1 .. $MAX) -> $num {
if @divisors_sums[$num] > $num {
@abundants.push($num);
# The sub { ... } and return are a workaround for the fact that Rakudo
# Perl 6 does not have last LABEL yet.
my $c = sub {
for @abundants -> $i {
if ((my $s = $i + $num) > $MAX) {
return;
}
else {
if (! @is_abundant_sum[$s]) {
$total += $s;
@is_abundant_sum[$s] = True;
}
}
}
};
$c();
}
}
say ((((1 + $MAX) * $MAX) +> 1)-$total);
Perl 6 示例