slow_prog.pl 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #!/usr/bin/perl
  2. # Smallest strong pseudoprime to base 2 with n prime factors
  3. # https://oeis.org/A180065
  4. # Known terms:
  5. # 2047, 15841, 800605, 293609485, 10761055201, 5478598723585, 713808066913201, 90614118359482705, 5993318051893040401
  6. =for comment
  7. # PARI/GP program:
  8. is_strong_psp(n, a=2)={ (bittest(n, 0) && !isprime(n) && n>8) || return; my(s=valuation(n-1, 2)); if(1==a=Mod(a, n)^(n>>s), return(1)); while(a!=-1 && s--, a=a^2); a==-1}; \\ A001262
  9. strong_fermat_psp(A, B, k, base) = A=max(A, vecprod(primes(k))); (f(m, l, p, j) = my(list=List()); forprime(q=p, sqrtnint(B\m, j), if(base%q != 0, my(v=m*q, t=q, r=nextprime(q+1)); while(v <= B, my(L=lcm(l, znorder(Mod(base, t)))); if(gcd(L, v) == 1, if(j==1, if(v>=A && if(k==1, !isprime(v), 1) && (v-1)%L == 0 && is_strong_psp(v, base), listput(list, v)), if(v*r <= B, list=concat(list, f(v, L, r, j-1)))), break); v *= q; t *= q))); list); vecsort(Vec(f(1, 1, 2, k)));
  10. a(n) = if(n < 2, return()); my(x=vecprod(primes(n)), y=2*x); while(1, my(v=strong_fermat_psp(x, y, n, 2)); if(#v >= 1, return(v[1])); x=y+1; y=2*x);
  11. =cut
  12. # Very hard to compute more terms...
  13. =for comment
  14. # Some upper-bounds:
  15. a(11) <= 40458813831093914176528685701
  16. a(12) <= 3461315300911389965986555018529761
  17. a(13) <= 1793888484612948579347804219906251
  18. a(14) <= 11204126171093532395238176008628640001
  19. a(15) <= 52763042375348388525807775606810431553349251
  20. a(16) <= 8490206016886862443343349923062834577705405389801
  21. a(17) <= 16466175808047026414728161638977648257386104008228485611
  22. a(18) <= 5344281976789774350298352596501700430295430104885257558315750001
  23. a(27) <= 7043155715130173703570458476044409843679195526432194529835594986452175531142548938830450109251
  24. =cut
  25. use 5.020;
  26. use warnings;
  27. use ntheory qw(:all);
  28. use experimental qw(signatures);
  29. sub divceil ($x,$y) { # ceil(x/y)
  30. my $q = divint($x, $y);
  31. ($q*$y == $x) ? $q : ($q+1);
  32. }
  33. sub fermat_pseudoprimes_in_range ($A, $B, $k, $base, $callback) {
  34. $A = vecmax($A, pn_primorial($k));
  35. sub ($m, $lambda, $p, $k, $u = undef, $v = undef) {
  36. if ($k == 1) {
  37. forprimes {
  38. my $t = $m*$_;
  39. if (($t-1)%$lambda == 0 and is_strong_pseudoprime($t, $base) and ($t-1)%znorder($base, $_) == 0) {
  40. $callback->($t);
  41. }
  42. } $u, $v;
  43. return;
  44. }
  45. my $s = rootint(divint($B, $m), $k);
  46. for(my $r; $p <= $s; $p = $r) {
  47. $r = next_prime($p);
  48. $base % $p == 0 and next;
  49. my $z = znorder($base, $p);
  50. my $L = lcm($lambda, $z);
  51. gcd($L, $m) == 1 or next;
  52. my $t = $m*$p;
  53. my $u = divceil($A, $t);
  54. my $v = divint($B, $t);
  55. if ($u <= $v) {
  56. __SUB__->($t, $L, $r, $k - 1, (($k==2 && $r>$u) ? $r : $u), $v);
  57. }
  58. }
  59. }->(1, 1, 2, $k);
  60. }
  61. sub a($n) {
  62. my $x = pn_primorial($n);
  63. my $y = 2*$x;
  64. #$x = Math::GMP->new("$x");
  65. #$y = Math::GMP->new("$y");
  66. for (;;) {
  67. my @arr;
  68. fermat_pseudoprimes_in_range($x, $y, $n, 2, sub($v) { push @arr, $v });
  69. if (@arr) {
  70. @arr = sort {$a <=> $b} @arr;
  71. return $arr[0];
  72. }
  73. $x = $y+1;
  74. $y = 2*$x;
  75. }
  76. }
  77. foreach my $n (2..100) {
  78. say "a($n) = ", a($n);
  79. }
  80. __END__
  81. a(2) = 2047
  82. a(3) = 15841
  83. a(4) = 800605
  84. a(5) = 293609485
  85. a(6) = 10761055201
  86. a(7) = 5478598723585