764 Asymmetric Diophantine Equation - difference of squares.pl 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #!/usr/bin/perl
  2. # Asymmetric Diophantine Equation
  3. # https://projecteuler.net/problem=764
  4. use 5.014;
  5. use warnings;
  6. use ntheory qw(:all);
  7. sub divisors_le {
  8. my ($n, $k) = @_;
  9. my @d = (1);
  10. my @pp = grep { $_->[0] <= $k } factor_exp($n);
  11. foreach my $pp (@pp) {
  12. my $p = $pp->[0];
  13. my $e = $pp->[1];
  14. my @t;
  15. my $r = 1;
  16. for my $i (1 .. $e) {
  17. $r = mulint($r, $p);
  18. foreach my $u (@d) {
  19. my $t = mulint($u, $r);
  20. push(@t, $t) if ($t <= $k);
  21. }
  22. }
  23. push @d, @t;
  24. }
  25. @d;
  26. }
  27. sub udivisors {
  28. my ($n) = @_;
  29. my @d = (1);
  30. my @pp = map { powint($_->[0], $_->[1]) } factor_exp($n);
  31. foreach my $p (@pp) {
  32. push @d, map { mulint($_, $p) } @d;
  33. }
  34. return sort { $a <=> $b } @d;
  35. }
  36. my $N = powint(10, 16);
  37. my $MOD = powint(10, 9);
  38. sub difference_of_two_squares_solutions {
  39. my ($n) = @_;
  40. my @solutions;
  41. my $limit = sqrtint($n);
  42. foreach my $d (divisors_le($n, $limit)) {
  43. #foreach my $d (divisors($n)) {
  44. #last if $d > $limit;
  45. my $p = $d;
  46. my $q = divint($n, $d);
  47. ($p + $q) % 2 == 0 or next;
  48. my $x = ($q + $p) >> 1;
  49. my $y = ($q - $p) >> 1;
  50. if ($y%4 == 0 and $y >= 1 and $x <= $N and ($y >> 2) <= $N and gcd($x, $y >> 2) == 1) {
  51. push @solutions, [$x, $y];
  52. }
  53. }
  54. return @solutions;
  55. }
  56. my $sum = 0;
  57. foreach my $y(1..sqrtint($N)) {
  58. if ($y % 1e4 == 0) {
  59. say "y = $y out of ", sqrtint($N), " (", sprintf("%.2f", $y / sqrtint($N) * 100), "%)";
  60. say "Sum = $sum";
  61. }
  62. #~ if ($y*$y*$y*$y > $N*$N) {
  63. #~ say "Last: $y";
  64. #~ last;
  65. #~ }
  66. my @d = difference_of_two_squares_solutions(powint($y, 4));
  67. foreach my $pair (@d) {
  68. #if ($pair->[1] % 4 == 0 and $pair->[1] <= $N and $pair->[0] <= $N and $pair->[0] >= 1 and $pair->[1] >= 1) {
  69. if (gcd($y, $pair->[0], $pair->[1] >> 2) == 1) {
  70. $sum = addmod($sum, addmod(addmod($pair->[0], ($pair->[1] >> 2), $MOD), $y, $MOD), $MOD);
  71. }
  72. #}
  73. }
  74. #foreach my $x(1..$N) {
  75. #~ for(my $x = 4; $x <= $N; $x += 4) {
  76. #~ ++$count;
  77. #~ my $z2 = $x*$x + $y*$y*$y*$y;
  78. #~ if ($z2 > $N*$N) {
  79. #~ say "Last x: $x";
  80. #~ last;
  81. #~ }
  82. #~ if (is_square($z2)) {
  83. #~ my $z = sqrtint($z2);
  84. #~ if (gcd($x>>2, $y, $z) == 1) {
  85. #~ say "[$x, $y, $z]";
  86. #~ $sum += ($x>>2) + $y + $z;
  87. #~ }
  88. #~ }
  89. #~ }
  90. }
  91. say "N = $N";
  92. say "Sum: $sum";
  93. __END__
  94. N = 10000000
  95. Sum: 248876211
  96. perl 764\ Asymmetric\ Diophantine\ Equation\ -\ difference\ of\ squares.pl 0.19s user 0.01s system 97% cpu 0.201 total
  97. y = 10000 out of 31622 (31.62%)
  98. y = 20000 out of 31622 (63.25%)
  99. y = 30000 out of 31622 (94.87%)
  100. N = 1000000000
  101. Sum: 258133745
  102. perl 764\ Asymmetric\ Diophantine\ Equation\ -\ difference\ of\ squares.pl 3.34s user 0.01s system 99% cpu 3.372 total