634 Numbers of the form a^2b^3.pl 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 19 August 2021
  4. # https://github.com/trizen
  5. # Numbers of the form a^2 * b^3, where a,b > 1.
  6. # https://projecteuler.net/problem=634
  7. # Runtime: 5 minutes, 41 seconds.
  8. use 5.020;
  9. use strict;
  10. use warnings;
  11. use ntheory qw(:all);
  12. use experimental qw(signatures);
  13. sub power_divisors ($n, $k = 1) {
  14. my @d = (1);
  15. my @pp = grep { $_->[1] >= $k } factor_exp($n);
  16. foreach my $pp (@pp) {
  17. my $p = $pp->[0];
  18. my $e = $pp->[1];
  19. my @t;
  20. for (my $i = $k ; $i <= $e ; $i += $k) {
  21. push @t, map { mulint($_, powint($p, $i)) } @d;
  22. }
  23. push @d, @t;
  24. }
  25. return @d;
  26. }
  27. sub p_634 ($n) {
  28. my $count = 0;
  29. foreach my $b (2 .. rootint($n, 3)) {
  30. my $b_cubed = powint($b, 3);
  31. my $a_limit = sqrtint(divint($n, $b_cubed));
  32. $count += $a_limit - 1;
  33. if (!is_square_free($b)) {
  34. next if ($a_limit <= 1);
  35. my $acc = 0;
  36. if ($b == 4) {
  37. $acc = 0;
  38. }
  39. elsif ($b == 9) {
  40. $acc = divint($a_limit, $b - 1);
  41. }
  42. elsif (is_powerful($b, 3)) {
  43. $acc = $a_limit - 1;
  44. }
  45. elsif (is_square($b)) {
  46. say "b = $b -- looping up to $a_limit (~10^", sprintf("%.2f", log($a_limit) / log(10)), ")";
  47. foreach my $a (2 .. $a_limit) {
  48. my $powerful = mulint(mulint($a, $a), $b_cubed);
  49. foreach my $d (power_divisors($powerful, 2 * 3)) {
  50. my $w = rootint($d, 3);
  51. if ($w >= 2 and $w < $b) {
  52. ++$acc;
  53. last;
  54. }
  55. }
  56. }
  57. }
  58. else {
  59. $acc = $a_limit - 1;
  60. }
  61. #say "f($b) = $acc with limit = $a_limit" if ($a_limit > 100);
  62. $count -= $acc;
  63. }
  64. }
  65. return $count;
  66. }
  67. p_634(2 * 1e4) == 130 or die "error";
  68. p_634(3 * 1e6) == 2014 or die "error";
  69. p_634(5 * 1e9) == 91255 or die "error";
  70. say p_634(mulint(9, powint(10, 18)));