066 Diophantine equation.pl 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 11 February 2019
  4. # https://github.com/trizen
  5. # https://projecteuler.net/problem=66
  6. # Runtime: 0.151s
  7. use 5.010;
  8. use strict;
  9. use warnings;
  10. use Math::GMPz;
  11. use ntheory qw(sqrtint is_square);
  12. use experimental qw(signatures);
  13. use constant {
  14. ONE => Math::GMPz->new(1),
  15. ZERO => Math::GMPz->new(0),
  16. };
  17. sub solve_pell ($n, $w = 1) {
  18. return () if is_square($n);
  19. my $x = sqrtint($n);
  20. my $y = $x;
  21. my $z = 1;
  22. my $r = 2 * $x;
  23. my ($e1, $e2) = (ONE, ZERO);
  24. my ($f1, $f2) = (ZERO, ONE);
  25. for (1 .. $n) {
  26. $y = $r * $z - $y;
  27. $z = ($n - $y * $y) / $z;
  28. $r = int(($x + $y) / $z);
  29. my $A = $e2 + $x * $f2;
  30. my $B = $f2;
  31. if ($z == 1 and $A**2 - $n * $B**2 == 1) {
  32. return ($A, $B);
  33. }
  34. ($e1, $e2) = ($e2, $r * $e2 + $e1);
  35. ($f1, $f2) = ($f2, $r * $f2 + $f1);
  36. }
  37. return ();
  38. }
  39. my %max = (x => 0, d => -1);
  40. foreach my $i (2 .. 1000) {
  41. is_square($i) && next;
  42. my $x = solve_pell($i);
  43. if ($x > $max{x}) {
  44. $max{x} = $x;
  45. $max{d} = $i;
  46. }
  47. }
  48. say $max{d};