chernick-carmichael_with_n_factors_sieve.pl 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #!/usr/bin/perl
  2. # Sieve for Chernick's "universal form" Carmichael number with n prime factors.
  3. # Inspired by the PARI program by David A. Corneth from OEIS A372238.
  4. # Finding A318646(10) takes ~9 minutes.
  5. # See also:
  6. # https://oeis.org/A318646
  7. # https://oeis.org/A372238/a372238.gp.txt
  8. use 5.036;
  9. use ntheory qw(:all);
  10. use Time::HiRes qw (time);
  11. sub isrem($m, $p, $n) {
  12. ( 6 * $m + 1) % $p == 0 and return;
  13. (12 * $m + 1) % $p == 0 and return;
  14. (18 * $m + 1) % $p == 0 and return;
  15. foreach my $k (2 .. $n - 2) {
  16. if (((9 * $m << $k) + 1) % $p == 0) {
  17. return;
  18. }
  19. }
  20. return 1;
  21. }
  22. sub remaindersmodp($p, $n) {
  23. grep { isrem($_, $p, $n) } (0 .. $p - 1);
  24. }
  25. sub remainders_for_primes($n, $primes) {
  26. my $res = [[0, 1]];
  27. foreach my $p (@$primes) {
  28. my @rems = remaindersmodp($p, $n);
  29. if (!@rems) {
  30. @rems = (0);
  31. }
  32. my @nres;
  33. foreach my $r (@$res) {
  34. foreach my $rem (@rems) {
  35. push @nres, [chinese($r, [$rem, $p]), lcm($p, $r->[1])];
  36. }
  37. }
  38. $res = \@nres;
  39. }
  40. sort { $a <=> $b } map { $_->[0] } @$res;
  41. }
  42. sub is($m, $n) {
  43. is_prime( 6 * $m + 1) || return;
  44. is_prime(12 * $m + 1) || return;
  45. is_prime(18 * $m + 1) || return;
  46. foreach my $k (2 .. $n - 2) {
  47. is_prime((9 * $m << $k) + 1) || return;
  48. }
  49. return 1;
  50. }
  51. sub deltas ($integers) {
  52. my @deltas;
  53. my $prev = 0;
  54. foreach my $n (@$integers) {
  55. push @deltas, $n - $prev;
  56. $prev = $n;
  57. }
  58. return \@deltas;
  59. }
  60. sub chernick_carmichael_factors($m, $n) {
  61. (6 * $m + 1, 12 * $m + 1, (map { (9 * $m << $_) + 1 } 1 .. $n - 2));
  62. }
  63. sub chernick_carmichael_with_n_factors($n) {
  64. my $maxp = 11;
  65. $maxp = 17 if ($n >= 8);
  66. $maxp = 29 if ($n >= 10);
  67. $maxp = 31 if ($n >= 12);
  68. my @primes = @{primes($maxp)};
  69. my @r = remainders_for_primes($n, \@primes);
  70. my @d = @{deltas(\@r)};
  71. my $s = vecprod(@primes);
  72. while ($d[0] == 0) {
  73. shift @d;
  74. }
  75. push @d, $r[0] + $s - $r[-1];
  76. my $m = $r[0];
  77. my $d_len = scalar(@d);
  78. my $t0 = time;
  79. my $prev_m = $m;
  80. my $two_power = vecmax(1 << ($n - 4), 1);
  81. for (my $j = 0 ; ; ++$j) {
  82. if ($m % $two_power == 0 and is($m, $n)) {
  83. return $m;
  84. }
  85. if ($j % 1e7 == 0 and $j > 0) {
  86. my $tdelta = time - $t0;
  87. say "Searching for a($n) with m = $m";
  88. say "Performance: ", (($m - $prev_m) / 1e9) / $tdelta, " * 10^9 terms per second";
  89. $t0 = time;
  90. $prev_m = $m;
  91. }
  92. $m += $d[$j % $d_len];
  93. }
  94. }
  95. foreach my $n (3 .. 9) {
  96. my $m = chernick_carmichael_with_n_factors($n);
  97. say "[$n] m = $m";
  98. foreach my $k ($n .. $n + 100) {
  99. my $c = vecprod(chernick_carmichael_factors($m, $k));
  100. if (is_carmichael($c)) {
  101. say "[$k] $c";
  102. }
  103. else {
  104. last;
  105. }
  106. }
  107. is_carmichael(vecprod(chernick_carmichael_factors($m, $n))) || die "not a Carmichael number";
  108. }
  109. __END__
  110. [3] m = 6
  111. [3] 294409
  112. [4] m = 56
  113. [4] 461574735553
  114. [5] m = 380
  115. [5] 26641259752490421121
  116. [6] 1457836374916028334162241
  117. [6] m = 380
  118. [6] 1457836374916028334162241
  119. [7] m = 780320
  120. [7] 24541683183872873851606952966798288052977151461406721
  121. [8] m = 950560
  122. [8] 53487697914261966820654105730041031613370337776541835775672321
  123. [9] 58571442634534443082821160508299574798027946748324125518533225605795841
  124. [9] m = 950560
  125. [9] 58571442634534443082821160508299574798027946748324125518533225605795841
  126. [10] m = 3208386195840
  127. [10] 24616075028246330441656912428380582403261346369700917629170235674289719437963233744091978433592331048416482649086961226304033068172880278517841921