Project Euler 87

ストレートにx^2 + y^3 + z^4を総当りでとけばよい。


どうせそれぞれの変数に入る素数の値候補は多くは無いので、
最初にリストにしてしまって、リストの3重ループで回す。


当然xのとりうる範囲は50000000の平方根より少ない。
yのとりうる範囲は50000000の立方根より少ない。
zのとりうる範囲は50000000の4乗根より少ない。

#project euler 87

use strict;
use warnings;
use POSIX qw( ceil );

sub isprime{
	my $target = $_[0];
	return 0 if( $target <= 1 );
	return 1 if( $target == 2 );
	return 0 if( $target % 2 == 0 );

	for( my $i = 3; $i <= ceil( sqrt( $target ) ); $i+=2 ){

		if( $target % $i == 0){

			return 0;
		}
	}
	return 1;
}

sub get_primearray{
	my $limit = $_[0];
	my @prime;
	return 0 if ( $limit < 1 );
	foreach( 1..$limit){
		if( isprime( $_ ) == 1 ){

			push( @prime, $_ );
		}
	}
	return @prime;
}

my $limit = 50000000;
my $sq_lim = ceil( $limit ** ( 1 / 2) );
my $cb_lim = ceil( $limit ** ( 1 / 3) );
my $fr_lim = ceil( $limit ** ( 1 / 4) );

print "square : calcurate to $sq_lim\n";
print "cube : calcurate to $cb_lim\n";
print "forth power : calcurate to $fr_lim\n";

my @sqarr = get_primearray( $sq_lim );
my @cbarr = get_primearray( $cb_lim );
my @frarr =get_primearray( $fr_lim );
my %expr;

print "for sqare : @sqarr\n";
print "for cube : @cbarr\n";
print "for fourth power : @frarr\n";

foreach my $x(@sqarr){
	foreach my $y( @cbarr ){
		foreach my $z( @frarr ){
			my $key = $x ** 2 + $y ** 3 + $z ** 4;
			if( $key >= $limit ){
				next;
			} else {
				$expr{$key} = 1;
			}
		}
	}
}
my $count = keys( %expr );
print "$count\n";

このあたりの問題の難易度差が激しい気がする。