prog.pl 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #!/usr/bin/perl
  2. # a(n) is the least prime p such that the concatenation p|n has exactly n prime factors with multiplicity.
  3. # https://oeis.org/A358596
  4. # Known terms:
  5. # 3, 2, 83, 2, 67, 41, 947, 4519, 15659081, 2843, 337957, 389, 1616171, 6132829, 422116888343, 24850181, 377519743, 194486417892947, 533348873, 324403, 980825013273164555563, 25691144027, 273933405157, 1238831928746353181, 311195507789, 129917586781, 2159120477658983490299
  6. use 5.036;
  7. use Math::GMPz;
  8. use ntheory qw(:all);
  9. use List::Util qw(uniq);
  10. sub divceil ($x,$y) { # ceil(x/y)
  11. my $q = divint($x, $y);
  12. (mulint($q, $y) == $x) ? $q : ($q+1);
  13. }
  14. sub almost_prime_numbers ($A, $B, $k, $valid_primes, $callback) {
  15. $A = vecmax($A, Math::GMPz->new(2)**$k);
  16. my $mod = powint(10, length($k));
  17. sub ($m, $lo, $j) {
  18. my $hi = rootint(divint($B, $m), $j);
  19. if ($lo > $hi) {
  20. return;
  21. }
  22. if ($j == 1) {
  23. # TODO: generate primes x that satisfiy the following congruence, including when gcd(m,mod) != 1:
  24. # m*x == k (mod 10^length(k))
  25. $lo = vecmax($lo, divceil($A, $m));
  26. if ($lo > $hi) {
  27. return;
  28. }
  29. if (gcd($m, $mod) == 1) {
  30. my $t = mulmod(invmod($m, $mod), $k, $mod);
  31. $t > $hi && return;
  32. $t += $mod while ($t < $lo);
  33. for (my $p = $t ; $p <= $hi ; $p += $mod) {
  34. if (exists($valid_primes->{$p})) {
  35. my $n = $m*$p;
  36. my ($q, $r) = divrem($n, $mod);
  37. if ($r == $k and is_prime($q)) {
  38. $B = $n if ($n < $B);
  39. $callback->($q);
  40. }
  41. }
  42. }
  43. return;
  44. }
  45. forprimes {
  46. if (exists $valid_primes->{$_}) {
  47. my $n = $m*$_;
  48. my ($q, $r) = divrem($n, $mod);
  49. if ($r == $k and is_prime($q)) {
  50. $B = $n if ($n < $B);
  51. $callback->($q);
  52. }
  53. }
  54. } $lo, $hi;
  55. return;
  56. }
  57. foreach my $p (@{primes($lo, $hi)}) {
  58. exists($valid_primes->{$p}) or next;
  59. __SUB__->($m*$p, $p, $j - 1);
  60. }
  61. }->(Math::GMPz->new(1), 2, $k);
  62. }
  63. sub a($n) {
  64. my $x = Math::GMPz->new(2)**$n;
  65. my $y = 3*$x;
  66. my %valid_primes;
  67. foreach my $p (@{primes($x, $x+1e5)}) {
  68. $valid_primes{$_} = 1 for uniq(factor($p . $n));
  69. }
  70. while (1) {
  71. my @arr;
  72. almost_prime_numbers($x, $y, $n, \%valid_primes, sub ($k) { push @arr, $k });
  73. @arr = sort { $a <=> $b } @arr;
  74. @arr and return $arr[0];
  75. $x = $y+1;
  76. $y = 3*$x;
  77. }
  78. }
  79. foreach my $n(1..100) {
  80. say "$n ", a($n);
  81. }
  82. __END__
  83. 1 3
  84. 2 2
  85. 3 83
  86. 4 2
  87. 5 67
  88. 6 41
  89. 7 947
  90. 8 4519
  91. 9 15659081
  92. 10 2843
  93. 11 337957
  94. 12 389
  95. 13 1616171
  96. 14 6132829
  97. 15 422116888343
  98. 16 24850181
  99. 17 377519743