prog.pl 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/perl
  2. # Smallest prime which is 1 more than a product of n distinct primes: a(n) is a prime and a(n) - 1 is a squarefree number with n prime factors.
  3. # https://oeis.org/A073918
  4. use 5.020;
  5. use ntheory qw(:all);
  6. use experimental qw(signatures);
  7. use Math::Prime::Util::GMP;
  8. use Math::GMPz;
  9. sub generate ($A, $B, $k, $callback) {
  10. $A = vecmax($A, pn_primorial($k));
  11. $A = Math::GMPz->new("$A");
  12. my $u = Math::GMPz::Rmpz_init();
  13. my $v = Math::GMPz::Rmpz_init();
  14. sub ($m, $lo, $k) {
  15. Math::GMPz::Rmpz_tdiv_q($u, $B, $m);
  16. Math::GMPz::Rmpz_root($u, $u, $k);
  17. my $hi = Math::GMPz::Rmpz_get_ui($u);
  18. if ($lo > $hi) {
  19. return;
  20. }
  21. if ($k == 1) {
  22. Math::GMPz::Rmpz_cdiv_q($u, $A, $m);
  23. if (Math::GMPz::Rmpz_fits_ulong_p($u)) {
  24. $lo = vecmax($lo, Math::GMPz::Rmpz_get_ui($u));
  25. }
  26. elsif (Math::GMPz::Rmpz_cmp_ui($u, $lo) > 0) {
  27. if (Math::GMPz::Rmpz_cmp_ui($u, $hi) > 0) {
  28. return;
  29. }
  30. $lo = Math::GMPz::Rmpz_get_ui($u);
  31. }
  32. if ($lo > $hi) {
  33. return;
  34. }
  35. forprimes {
  36. Math::GMPz::Rmpz_mul_ui($v, $m, $_);
  37. Math::GMPz::Rmpz_add_ui($v, $v, 1);
  38. my $s = Math::GMPz::Rmpz_get_str($v, 10);
  39. if (Math::Prime::Util::GMP::is_prime($s)) {
  40. my $r = Math::GMPz::Rmpz_init_set($v);
  41. #say("Found upper-bound: ", $r);
  42. $B = $r if ($r < $B);
  43. $callback->($r);
  44. }
  45. } $lo, $hi;
  46. return;
  47. }
  48. foreach my $p (@{primes($lo, $hi)}) {
  49. __SUB__->($m*$p, $p+1, $k-1);
  50. }
  51. }->(Math::GMPz->new(1), 2, $k);
  52. }
  53. sub a($n) {
  54. if ($n == 0) {
  55. return 1;
  56. }
  57. my $x = Math::GMPz->new(pn_primorial($n));
  58. my $y = 2*$x;
  59. while (1) {
  60. #say("Sieving range: [$x, $y]");
  61. my @v;
  62. generate($x, $y, $n, sub ($k) {
  63. push @v, $k;
  64. });
  65. @v = sort { $a <=> $b } @v;
  66. if (scalar(@v) > 0) {
  67. return $v[0];
  68. }
  69. $x = $y+1;
  70. $y = 2*$x;
  71. }
  72. }
  73. foreach my $n (1..100) {
  74. say "$n ", a($n);
  75. }