squarefree_omega_palindromes.pl 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #!/usr/bin/perl
  2. # Smallest squarefree palindrome with exactly n distinct prime factors.
  3. # https://oeis.org/A046399
  4. # Known terms:
  5. # 1, 2, 6, 66, 858, 6006, 222222, 22444422, 244868442, 6434774346, 438024420834, 50146955964105, 2415957997595142, 495677121121776594, 22181673755737618122, 8789941164994611499878
  6. # Corrected term:
  7. # a(15) = 5521159517777159511255
  8. # New term found by Michael S. Branicky:
  9. # a(16) = 477552751050050157255774
  10. # Lower-bounds:
  11. # a(17) > 252020044615415406440021243
  12. # a(17) > 252020044615424516440020252
  13. # Timings:
  14. # a(12) is found in 0.2 seconds
  15. # a(13) is found in 6.5 seconds
  16. # a(14) is found in 9.7 seconds
  17. # a(15) is found in 17 minutes
  18. # While searching for a(17), it took 9 hours to check the range [63005011153853239757078527, 126010022307706479514157054].
  19. # While searching for a(17), it took 33 hours to check the range [126010022307707703220010621, 252020044615415406440021243]
  20. # Tried to sieve the range [252020044615424516440020252, 282020044615424516440020282], but the program didn't finish after 8 hours... (I had to stop the program after 8 hours)
  21. use 5.020;
  22. use ntheory qw(:all);
  23. use experimental qw(signatures);
  24. use Math::GMPz;
  25. sub squarefree_omega_palindromes ($A, $B, $k, $callback) {
  26. $A = vecmax($A, pn_primorial($k));
  27. $A = Math::GMPz->new("$A");
  28. my $u = Math::GMPz::Rmpz_init();
  29. my $v = Math::GMPz::Rmpz_init();
  30. sub ($m, $lo, $k) {
  31. Math::GMPz::Rmpz_tdiv_q($u, $B, $m);
  32. Math::GMPz::Rmpz_root($u, $u, $k);
  33. my $hi = Math::GMPz::Rmpz_get_ui($u);
  34. if ($lo > $hi) {
  35. return;
  36. }
  37. if ($k == 1) {
  38. Math::GMPz::Rmpz_cdiv_q($u, $A, $m);
  39. if (Math::GMPz::Rmpz_fits_ulong_p($u)) {
  40. $lo = vecmax($lo, Math::GMPz::Rmpz_get_ui($u));
  41. }
  42. elsif (Math::GMPz::Rmpz_cmp_ui($u, $lo) > 0) {
  43. if (Math::GMPz::Rmpz_cmp_ui($u, $hi) > 0) {
  44. return;
  45. }
  46. $lo = Math::GMPz::Rmpz_get_ui($u);
  47. }
  48. if ($lo > $hi) {
  49. return;
  50. }
  51. foreach my $p (@{primes($lo, $hi)}) {
  52. Math::GMPz::Rmpz_mul_ui($v, $m, $p);
  53. my $s = Math::GMPz::Rmpz_get_str($v, 10);
  54. if ($s eq reverse($s)) {
  55. my $r = Math::GMPz::Rmpz_init_set($v);
  56. say("Found upper-bound: ", $r);
  57. $B = $r if ($r < $B);
  58. $callback->($r);
  59. }
  60. }
  61. return;
  62. }
  63. my $z = Math::GMPz::Rmpz_init();
  64. foreach my $p (@{primes($lo, $hi)}) {
  65. if ($p == 5 and Math::GMPz::Rmpz_even_p($m)) {
  66. ## last digit can't be zero
  67. }
  68. else {
  69. Math::GMPz::Rmpz_mul_ui($z, $m, $p);
  70. __SUB__->($z, $p+1, $k-1);
  71. }
  72. }
  73. }->(Math::GMPz->new(1), 2, $k);
  74. }
  75. sub a($n) {
  76. if ($n == 0) {
  77. return 1;
  78. }
  79. #my $x = Math::GMPz->new(pn_primorial($n));
  80. my $x = Math::GMPz->new("252020044615424516440020252");
  81. #my $y = (5*$x)>>2;
  82. my $y = Math::GMPz->new("282020044615424516440020282");
  83. while (1) {
  84. say("Sieving range: [$x, $y]");
  85. my @v;
  86. squarefree_omega_palindromes($x, $y, $n, sub ($k) {
  87. push @v, $k;
  88. });
  89. @v = sort { $a <=> $b } @v;
  90. if (scalar(@v) > 0) {
  91. return $v[0];
  92. }
  93. $x = $y+1;
  94. $y = (5*$x)>>2;
  95. }
  96. }
  97. foreach my $n (17) {
  98. say "a($n) = ", a($n);
  99. }