prog_squarefree.pl 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #!/usr/bin/perl
  2. # a(n) = smallest pseudoprime to base 2 with n prime factors.
  3. # https://oeis.org/A007011
  4. # Known terms:
  5. # 341, 561, 11305, 825265, 45593065, 370851481, 38504389105, 7550611589521, 277960972890601, 32918038719446881, 1730865304568301265, 606395069520916762801, 59989606772480422038001, 6149883077429715389052001, 540513705778955131306570201, 35237869211718889547310642241
  6. # Lower-bounds:
  7. # a(33) > 549407656919731418096241718792164293317568547009840344974835958463
  8. # a(34) > 76367664311842667115377598912110836771142028034367807425335971762323
  9. # Upper-bounds:
  10. # a(35) <= 39861441152136913409974961298453657087970515495885529645785368112405601
  11. # It took 2 hours and 12 minutes to find a(30).
  12. # It took 5 hours to find a(32).
  13. # It took 3 hours and 45 minutes to find a(33).
  14. # It took 1 hour and 5 minutes to find a(34).
  15. use 5.036;
  16. use Math::GMPz;
  17. use ntheory qw(:all);
  18. sub squarefree_fermat_pseudoprimes_in_range ($A, $B, $k, $base, $callback) {
  19. $A = vecmax($A, pn_primorial($k));
  20. $A = Math::GMPz->new("$A");
  21. $B = Math::GMPz->new("$B");
  22. my $u = Math::GMPz::Rmpz_init();
  23. my $v = Math::GMPz::Rmpz_init();
  24. sub ($m, $L, $lo, $k) {
  25. Math::GMPz::Rmpz_tdiv_q($u, $B, $m);
  26. Math::GMPz::Rmpz_root($u, $u, $k);
  27. my $hi = Math::GMPz::Rmpz_get_ui($u);
  28. if ($lo > $hi) {
  29. return;
  30. }
  31. if ($k == 1) {
  32. Math::GMPz::Rmpz_cdiv_q($u, $A, $m);
  33. if (Math::GMPz::Rmpz_fits_ulong_p($u)) {
  34. $lo = vecmax($lo, Math::GMPz::Rmpz_get_ui($u));
  35. }
  36. elsif (Math::GMPz::Rmpz_cmp_ui($u, $lo) > 0) {
  37. if (Math::GMPz::Rmpz_cmp_ui($u, $hi) > 0) {
  38. return;
  39. }
  40. $lo = Math::GMPz::Rmpz_get_ui($u);
  41. }
  42. if ($lo > $hi) {
  43. return;
  44. }
  45. Math::GMPz::Rmpz_invert($v, $m, $L);
  46. if (Math::GMPz::Rmpz_cmp_ui($v, $hi) > 0) {
  47. return;
  48. }
  49. if (Math::GMPz::Rmpz_fits_ulong_p($L)) {
  50. $L = Math::GMPz::Rmpz_get_ui($L);
  51. }
  52. my $t = Math::GMPz::Rmpz_get_ui($v);
  53. $t > $hi && return;
  54. $t += $L while ($t < $lo);
  55. for (my $p = $t ; $p <= $hi ; $p += $L) {
  56. if (is_prime($p) and $base % $p != 0) {
  57. Math::GMPz::Rmpz_mul_ui($v, $m, $p);
  58. Math::GMPz::Rmpz_sub_ui($u, $v, 1);
  59. if (Math::GMPz::Rmpz_divisible_ui_p($u, znorder($base, $p))) {
  60. my $value = Math::GMPz::Rmpz_init_set($v);
  61. say "Found upper-bound: $value";
  62. $B = $value if ($value < $B);
  63. $callback->($value);
  64. }
  65. }
  66. }
  67. return;
  68. }
  69. my $t = Math::GMPz::Rmpz_init();
  70. my $lcm = Math::GMPz::Rmpz_init();
  71. foreach my $p (@{primes($lo, $hi)}) {
  72. $base % $p == 0 and next;
  73. my $z = znorder($base, $p);
  74. Math::GMPz::Rmpz_gcd_ui($Math::GMPz::NULL, $m, $z) == 1 or next;
  75. Math::GMPz::Rmpz_lcm_ui($lcm, $L, $z);
  76. Math::GMPz::Rmpz_mul_ui($t, $m, $p);
  77. __SUB__->($t, $lcm, $p + 1, $k - 1);
  78. }
  79. }
  80. ->(Math::GMPz->new(1), Math::GMPz->new(1), 2, $k);
  81. }
  82. sub a($n) {
  83. if ($n == 0) {
  84. return 1;
  85. }
  86. say "Searching for a($n)";
  87. my $x = Math::GMPz->new(pn_primorial($n));
  88. my $y = 2*$x;
  89. while (1) {
  90. say("Sieving range: [$x, $y]");
  91. my @v;
  92. squarefree_fermat_pseudoprimes_in_range($x, $y, $n, 2, sub ($k) {
  93. push @v, $k;
  94. });
  95. @v = sort { $a <=> $b } @v;
  96. if (scalar(@v) > 0) {
  97. return $v[0];
  98. }
  99. $x = $y+1;
  100. $y = 2*$x;
  101. }
  102. }
  103. foreach my $n (35) {
  104. say "a($n) = ", a($n);
  105. }
  106. __END__
  107. 2 341
  108. 3 561
  109. 4 11305
  110. 5 825265
  111. 6 45593065
  112. 7 370851481
  113. 8 38504389105
  114. 9 7550611589521
  115. 10 277960972890601
  116. 11 32918038719446881
  117. 12 1730865304568301265
  118. 13 606395069520916762801
  119. 14 59989606772480422038001
  120. 15 6149883077429715389052001
  121. 16 540513705778955131306570201
  122. 17 35237869211718889547310642241
  123. 18 13259400431578770557375638157521
  124. 19 580827911915963785382253469211401
  125. 20 292408776547176479576081475390697801
  126. 21 39498823114155235923831808284152901601
  127. 22 3284710806953570725820888298298841565601
  128. 23 327373784481535488655521620744179013043601
  129. 24 221404014114397213806721960178887462402717201
  130. 25 43691666165877828056799483424028795272585383601
  131. 26 13213974925373194568934435211730355813060799098001
  132. 27 1952204134080476076724242017017925744953021675628161
  133. 28 633922683896008820507659141940205847766668463614120801
  134. 29 208615777921466463779477993429576353802684390620173966001
  135. 30 44091058061027666417635106691235215695970713110442194459201
  136. 31 2884167509593581480205474627684686008624483147814647841436801
  137. 32 2214362930783528605057288166084711828471950070626477770522049201
  138. 33 846160422741542455111837894473050187248594912573350734967810185601
  139. 34 152871247604711789212068696541727000750702435080280578363228173885601