前回の分解を、もうちょっとちゃんと考えて、改良してみる。
a > 0として、
と分解できるとすると、
ここで、
と置くと、a3,b3は正だから、両方とも1〜a-1。
b3をその範囲で決めて、b1とb2も決まったとすると、
a1の2次方程式と見て、判別式は、
a = a3 + cb3より、
判別式より、a2 ≧ cb2 ならこれは常に成り立つ。
そうでなければ、
sub alg_resolve {
my @result;
my ($a, $b, $c) = @{$_[0]};
if($a < 0) {
$a = -$a;
$b = -$b;
}
if($b * $b < 4 * ($a - $c)) {
return \@result;
}
else {
my $det = $a * $a - $c * $b * $b;
if($det >= 0) {
my $s = sqrt($det);
my $alpha = ($a - $s) / (2 * $c);
my $beta = ($a + $s + 2 * $c - 1) / (2 * $c);
for(my $b3 = 1; $b3 <= $alpha; $b3++) {
alg_resolve_core($a, $b, $b3, $c, \@result);
}
for(my $b3 = $beta; $b3 <= ($a - 1) / $c; $b3++) {
alg_resolve_core($a, $b, $b3, $c, \@result);
}
}
else {
for(my $b3 = 1; $b3 <= ($a - 1) / $c; $b3++) {
alg_resolve_core($a, $b, $b3, $c, \@result);
}
}
}
return \@result;
}sub alg_resolve_core {
my ($a, $b, $b3, $c, $result) = @_;
my $a3 = $a - $b3 * $c;
my $det = $b * $b - 4 * $b3 * $a3;
next if $det < 0;
my $r = sqrt($det);
next if $r * $r != $det;
for(my $b1 = 1; $b1 * $b1 <= $b3; $b1++) {
if($b3 % $b1 == 0) {
my $b2 = $b3 / $b1;
my ($a1, $a2);
if(($b - $r) % (2 * $b2) == 0) {
$a1 = ($b - $r) / (2 * $b2);
if($a3 % $a1 == 0) {
$a2 = $a3 / $a1;
alg_push($result, [ $a1, $b1, $c ]);
alg_push($result, [ $a2, $b2, $c ]);
}
}
if(($b + $r) % (2 * $b2) == 0) {
$a1 = ($b + $r) / (2 * $b2);
if($a3 % $a1 == 0) {
$a2 = $a3 / $a1;
alg_push($result, [ $a1, $b1, $c ]);
alg_push($result, [ $a2, $b2, $c ]);
}
}
}
}
}sub alg_push {
my ($ary, $a) = @_;
for my $e(@{$ary}) {
if($e->[0] == $a->[0] && $e->[1] == $a->[1]) {
return;
}
}
push @{$ary}, $a;
}