erdos_carmichael_generate_from_prefix.pl 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. #!/usr/bin/perl
  2. # Erdos construction method for Carmichael numbers:
  3. # 1. Choose an even integer L with many prime factors.
  4. # 2. Let P be the set of primes d+1, where d|L and d+1 does not divide L.
  5. # 3. Find a subset S of P such that prod(S) == 1 (mod L). Then prod(S) is a Carmichael number.
  6. # Alternatively:
  7. # 3. Find a subset S of P such that prod(S) == prod(P) (mod L). Then prod(P) / prod(S) is a Carmichael number.
  8. use 5.020;
  9. use warnings;
  10. use ntheory qw(:all);
  11. use List::Util qw(shuffle);
  12. use experimental qw(signatures);
  13. use Math::GMPz;
  14. # Modular product of a list of integers
  15. sub vecprodmod ($arr, $mod) {
  16. #~ if ($mod > ~0) {
  17. #~ my $prod = Math::GMPz->new(1);
  18. #~ foreach my $k(@$arr) {
  19. #~ $prod = ($prod * $k) % $mod;
  20. #~ }
  21. #~ return $prod;
  22. #~ }
  23. if ($mod < ~0) {
  24. my $prod = 1;
  25. foreach my $k(@$arr) {
  26. $prod = mulmod($prod, $k, $mod);
  27. }
  28. return $prod;
  29. }
  30. my $prod = 1;
  31. foreach my $k (@$arr) {
  32. $prod = Math::Prime::Util::GMP::mulmod($prod, $k, $mod);
  33. }
  34. Math::GMPz->new($prod);
  35. }
  36. # Primes p such that p-1 divides L and p does not divide L
  37. sub lambda_primes ($L) {
  38. #grep { ($L % $_) != 0 } grep { $_ > 2 and is_prime($_) } map { $_ + 1 }
  39. #map { Math::GMPz->new($_)}
  40. # divisors($L);
  41. grep { ($_ > 2) and (($L % $_) != 0) and is_prime($_) } map { ($_ >= ~0) ? (Math::GMPz->new($_)+1) : ($_ + 1) } divisors($L);
  42. }
  43. #my @prefix = (3, 5, 17, 23, 29, 53, 83, 89);
  44. #my @prefix = (3,5,17,23, 29);
  45. #my @prefix = (3, 5, 17, 23, 29, 53, 83, 89);
  46. #my @prefix = (3, 5, 17, 23, 29, 53, 83, 89, 113, 353, 617, 2003, 2549);
  47. #my @prefix = (3, 5, 17, 23, 29, 53, 83, 89, 113, 353, 617);
  48. #my @prefix = (3, 5, 17, 23, 29, 53, 83, 89, 113, 419, 449, 617);
  49. #my @prefix = (3, 5, 17, 23, 29, 53, 83, 89, 113, 257, 353, 449, 617, 1409, 2003);
  50. #my @prefix = (3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 1409, 2003);
  51. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353, 617, 1409, 2003, 2549, 3137, 9857, 10193, 16073, 68993, 202049, 275969, 1500929, 18386369]
  52. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 2003, 2297, 2549, 3137, 9857, 10193, 68993, 88397, 93809, 5850209, 8044037, 18386369]
  53. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 2003, 2549, 3137, 4019, 4289, 10193, 16073, 21977, 38459, 50513, 52529, 76649, 93809, 97553]
  54. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 1409, 2003, 2549, 8009, 9857, 23297, 50513, 68993, 275969, 375233, 1500929, 3232769, 18386369]
  55. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 1409, 2003, 2297, 2549, 3329, 8009, 10193, 16073, 23297, 50177, 93809, 202049, 275969, 656657, 18386369]
  56. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019, 7547, 9857, 10193, 16073, 17837, 23297, 68993, 88397, 93809, 202049, 896897, 1500929, 2475089, 8044037, 18386369]
  57. #my @prefix = (3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019);
  58. #my @prefix = (3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353);
  59. #my @prefix = (3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019);
  60. #my @prefix = (3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019);
  61. # primes(2, 15500).grep{ .dec.is_smooth(43) }.grep{ gcd(.phi, [3, 5, 17, 23, 29].prod) == 1 }
  62. # => [2, 3, 5, 17, 23, 29, 53, 83, 89, 113, 149, 173, 197, 257, 353, 419, 449, 593, 617, 677, 683, 947, 1217, 1373, 1409, 1559, 1613, 2003, 2129, 2237, 2297, 2357, 2543, 2549, 2663, 2729, 2753, 2927, 3137, 3257, 3329, 3389, 3527, 3719, 4019, 4733, 4817, 5333, 5477, 6449, 6689, 6917, 7253, 7547, 7937, 8009, 8429, 8513, 8867, 9473, 9857, 9923, 10169, 10193, 12959, 13313, 13469, 13553, 13859, 14897, 15137, 15377, 15467]
  63. my @prefix = (
  64. #3, 5, 17, 23, 29, 53, 83, 89, 113, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019, 7547, 9857, 10193, 16073, 17837, 23297, 68993, 88397, 93809, 202049, 896897
  65. #3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019, 9923, 10193, 13553, 308309, 486179, 656657
  66. #3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019, 9923, 10193, 13553, 308309, 486179, 656657, 896897, 902903, 1500929, 1610753, 1944713, 2063777, 2540033, 2818817, 3232769, 6071297, 18386369
  67. #3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019, 9923, 10193, 13553, 308309, 486179, 656657, 896897, 902903, 1500929, 1610753, 1944713, 2063777, 2540033, 2818817, 3232769, 6071297, 18386369, 22629377, 25281257, 31115393, 33020417
  68. #3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 2003, 2297, 2549, 3137, 9857, 10193, 68993, 88397, 93809, 5850209, 8044037, 18386369
  69. #3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 2003, 2297, 2549, 3137, 9857, 10193, 68993, 88397, 93809, 5850209, 8044037, 18386369, 2059273217
  70. # 3, 5, 17, 23, 29, 53, 83, 89, 113, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019, 7547, 9857, 10193, 16073, 17837, 23297, 68993, 88397, 93809, 202049, 896897, 1500929, 2475089, 8044037, 18386369, 2059273217
  71. #3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 10193, 3232769, 6071297, 18386369
  72. # 3, 5, 17, 23, 29, 53, 83, 89, 113, 353, 449, 617, 2003, 2297, 2549, 3137, 10193, 18386369
  73. #3, 5, 17, 23, 29, 53, 83, 89, 113, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019, 7547, 9857, 10193, 16073, 17837, 23297,
  74. #3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 617, 1409, 2003, 2549, 3137, 9857, 10193, 16073, 68993, 18386369
  75. #3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 4019, 4289, 7547, 9857, 10193, 16073, 68993, 88397, 93809
  76. #3, 5, 17, 23, 29, 53, 89, 197
  77. #3, 5, 17, 23, 29, 53, 89, 197, 617
  78. # 3, 5, 17, 23, 29, 197, 617, 1217, 6689, 14897, 16073, 20483, 46817, 50513, 68993, 76343, 81929,
  79. #3, 5, 17, 23, 29, 197, 419, 449, 617, 1217, 2129, 3137, 9857, 10193, 16073, 68993, 18386369
  80. #3, 5, 17, 23, 29, 43, 53, 89, 113, 127, 157, 257, 353, 397, 449, 617, 1093, 1499, 2731
  81. #3, 5, 17, 23, 29, 53, 83, 89, 113, 353,
  82. #3, 5, 17, 23, 29, 53, 83, 89, 113, 149, 173, 197, 257, 263, 269, 293, 353, 359, 383
  83. # 3, 5, 17, 23, 29, 53, 83, 89, 113, 149, 173, 197, 257, 353
  84. # 3, 5, 17, 23, 29, 53, 83, 89, 113, 149, 173, 197, 257, 353, 419, 449, 593, 617, 677, 683, 947, 1217, 1373,
  85. # 3, 5, 17, 23, 29, 53, 83, 89, 113, 149, 197, 257, 353, 419, 449, 593, 617, 677, 683, 1217, 1373, 1409, 1559, 1613
  86. # 3, 5, 17, 23, 29, 53, 83, 89, 113
  87. #~ 3, 5, 17, 23, 29, 53, 83, 89, 113, 149, 173, 197, 257, 263, 269, 293, 353, 359, 383
  88. #~ A328691
  89. #~ A329460
  90. #~ #Constructing Carmichael numbers throughimproved subset-product algorithms
  91. #~ 1.893
  92. #~ The smallest Abundant number which is also pseudoprime (base-2).
  93. #~ Shyam Sunder Gupta
  94. #~ 171800042106877185
  95. #~ 10-11-2019
  96. #~ 3470207934739664512679701940114447720865
  97. #3, 5, 17, 23, 29, 53, 83, 89, 113, 149, 197, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019
  98. #3, 5, 17, 23, 29, 53, 83, 89, 2237, 2297, 3527, 8009, 15137, 24683, 26489,
  99. #3, 5, 17, 23, 29, 53, 83, 89, 2237, 2297, 3527, 8009, 15137, 24683, 26489, 49193, 50513, 56417, 77573, 93809, 98729, 105953, 202049, 250433
  100. #3, 5, 17, 23, 29, 53, 83, 89, 113, 149, 173, 197, 257, 353, 419, 449, 593, 617, 677, 683, 947, 1217, 1373, 1409, 1559
  101. #3, 5, 17, 23, 29, 53, 89, 113, 197, 257, 353, 419, 449, 617, 677, 1217, 1373, 1409, 2003, 2129, 2549, 2663, 2927, 3137, 3329, 3389, 3719, 4733, 6689, 6917, 7547, 8009, 8513, 9857, 10193, 13313, 13553, 14897
  102. #3, 5, 17, 23, 29, 53, 89, 113, 197, 257, 353, 419, 449, 617, 677, 1217, 1373, 1409, 2003, 2129, 2549, 2663, 2927, 3137, 3329, 3389, 3719, 4733, 6689, 6917, 7547, 8009, 8513, 9857, 10193, 13313, 13553, 14897, 15809, 17837, 18773, 19457, 20483, 21737, 23297, 25169, 27437, 30977, 31769, 34607, 35153, 38039, 40433, 46817,
  103. #3, 5, 17, 23, 29, 89, 113, 197, 257, 353, 449, 617, 1373, 1409, 2663, 3137, 3389, 7547, 9857, 13553, 30977, 50177, 65537, 68993, 114689, 120737, 130439, 166013, 170369, 268913, 275969, 470597, 495617, 521753, 614657, 913067, 1075649, 1103873
  104. #3, 5, 17, 23, 29, 53, 83, 89, 113, 149, 197, 257, 353, 419, 449, 593, 617, 677, 683, 1217, 1373, 1409, 1559, 1613, 2003, 2129, 2297, 2357, 2543, 2549, 2663, 2729, 2927, 3137, 3257, 3329, 3389, 3719, 4019, 4733, 5477, 6449, 6689
  105. #256392945019638502140697184374123648403371443140710905
  106. 3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019, 9923
  107. #3, 5, 17, 23, 29, 53, 83, 89, 113, 149, 173, 197, 257, 263, 269, 293, 353, 359, 383
  108. );
  109. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353, 617, 1409, 2003, 2549, 3137, 9857, 10193, 16073, 68993, 202049, 275969, 1500929, 18386369]
  110. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 2003, 2297, 2549, 3137, 9857, 10193, 68993, 88397, 93809, 5850209, 8044037, 18386369]
  111. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 2003, 2549, 3137, 4019, 4289, 10193, 16073, 21977, 38459, 50513, 52529, 76649, 93809, 97553]
  112. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 1409, 2003, 2549, 8009, 9857, 23297, 50513, 68993, 275969, 375233, 1500929, 3232769, 18386369]
  113. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 2003, 2297, 2549, 3137, 9857, 10193, 68993, 88397, 93809, 5850209, 8044037, 18386369, 2059273217]
  114. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 1409, 2003, 2297, 2549, 3329, 8009, 10193, 16073, 23297, 50177, 93809, 202049, 275969, 656657, 18386369]
  115. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 1409, 2003, 2549, 8009, 9857, 23297, 50513, 68993, 275969, 375233, 1500929, 3232769, 18386369, 1176727553]
  116. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019, 7547, 9857, 10193, 16073, 17837, 23297, 68993, 88397, 93809, 202049, 896897, 1500929, 2475089, 8044037, 18386369]
  117. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019, 9923, 10193, 13553, 308309, 486179, 656657, 896897, 902903, 1500929, 1610753, 1944713, 2063777, 2540033, 2818817, 3232769, 6071297, 18386369, 22629377, 25281257, 31115393, 33020417]
  118. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 2003, 2297, 2549, 3137, 9857, 10193, 68993, 88397, 93809, 5850209, 8044037, 18386369]
  119. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 2003, 2549, 3137, 4019, 4289, 10193, 16073, 21977, 38459, 50513, 52529, 76649, 93809, 97553]
  120. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 1409, 2003, 2549, 8009, 9857, 23297, 50513, 68993, 275969, 375233, 1500929, 3232769, 18386369]
  121. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 197, 353, 449, 617, 1409, 2003, 2297, 2549, 3329, 8009, 10193, 16073, 23297, 50177, 93809, 202049, 275969, 656657, 18386369]
  122. #~ [3, 5, 17, 23, 29, 53, 83, 89, 113, 257, 353, 449, 617, 1409, 2003, 2297, 2549, 3137, 3329, 4019, 7547, 9857, 10193, 16073, 17837, 23297, 68993, 88397, 93809, 202049, 896897, 1500929, 2475089, 8044037, 18386369]
  123. #my @prefix = (3, 5, 17, 23, 29);
  124. my $prefix_prod = Math::GMPz->new(vecprod(@prefix));
  125. my $multiplier = lcm(map {$_-1} @prefix);
  126. sub method_1 ($L) { # smallest numbers first
  127. (vecall { ($L % ($_-1)) == 0 } @prefix) or return;
  128. my @P = lambda_primes($L);
  129. @P = grep {
  130. (($prefix_prod % $_) == 0)
  131. ? 1
  132. : Math::Prime::Util::GMP::gcd(Math::Prime::Util::GMP::totient(Math::Prime::Util::GMP::mulint($prefix_prod, $_)), Math::Prime::Util::GMP::mulint($prefix_prod, $_)) eq '1'
  133. } @P;
  134. #vecprodmod(@P, 3*5*17*23) == 0 or return;
  135. #vecprodmod(\@P, 3*5*17*23*29) == 0 or return;
  136. if (@prefix) {
  137. vecprodmod(\@P, $prefix_prod) == 0 or return;
  138. }
  139. #return if (vecprod(@P) < ~0);
  140. # @P = grep { $_ > 257 } @P;
  141. #@P = grep { $_ > $prefix[-1] } @P;
  142. @P = grep { gcd($prefix_prod, $_) == 1 } @P;
  143. say "# Testing: $L -- ", scalar(@P);
  144. my $n = scalar(@P);
  145. my @orig = @P;
  146. my $max = 1e3;
  147. my $max_k = 30;
  148. my $L_rem = invmod($prefix_prod, $L);
  149. foreach my $k (1 .. @P) {
  150. #next if (binomial($n, $k) > 1e6);
  151. next if ($k > $max_k);
  152. @P = @orig;
  153. my $count = 0;
  154. forcomb {
  155. if (vecprodmod([@P[@_]], $L) == $L_rem) {
  156. say vecprod(@P[@_], $prefix_prod);
  157. }
  158. lastfor if (++$count > $max);
  159. } $n, $k;
  160. next if (binomial($n, $k) < $max);
  161. @P = reverse(@P);
  162. $count = 0;
  163. forcomb {
  164. if (vecprodmod([@P[@_]], $L) == $L_rem) {
  165. say vecprod(@P[@_], $prefix_prod);
  166. }
  167. lastfor if (++$count > $max);
  168. } $n, $k;
  169. for (1..2) {
  170. @P = shuffle(@P);
  171. $count = 0;
  172. forcomb {
  173. if (vecprodmod([@P[@_]], $L) == $L_rem) {
  174. say vecprod(@P[@_], $prefix_prod);
  175. }
  176. lastfor if (++$count > $max);
  177. } $n, $k;
  178. }
  179. }
  180. my $B = vecprodmod([@P, $prefix_prod], $L);
  181. my $T = Math::GMPz->new(Math::Prime::Util::GMP::vecprod(@P));
  182. foreach my $k (1 .. @P) {
  183. #next if (binomial($n, $k) > 1e6);
  184. last if ($k > $max_k);
  185. @P = @orig;
  186. my $count = 0;
  187. forcomb {
  188. if (vecprodmod([@P[@_]], $L) == $B) {
  189. my $S = Math::GMPz->new(Math::Prime::Util::GMP::vecprod(@P[@_]));
  190. say vecprod($prefix_prod, $T / $S) if ($T != $S);
  191. }
  192. lastfor if (++$count > $max);
  193. } $n, $k;
  194. next if (binomial($n, $k) < $max);
  195. @P = reverse(@P);
  196. $count = 0;
  197. forcomb {
  198. if (vecprodmod([@P[@_]], $L) == $B) {
  199. my $S = Math::GMPz->new(Math::Prime::Util::GMP::vecprod(@P[@_]));
  200. say vecprod($prefix_prod, $T / $S) if ($T != $S);
  201. }
  202. lastfor if (++$count > $max);
  203. } $n, $k;
  204. for (1..2) {
  205. @P = shuffle(@P);
  206. $count = 0;
  207. forcomb {
  208. if (vecprodmod([@P[@_]], $L) == $B) {
  209. my $S = Math::GMPz->new(Math::Prime::Util::GMP::vecprod(@P[@_]));
  210. say vecprod($prefix_prod, $T / $S) if ($T != $S);
  211. }
  212. lastfor if (++$count > $max);
  213. } $n, $k;
  214. }
  215. }
  216. }
  217. use Math::GMPz;
  218. my %seen;
  219. my $count = 0;
  220. foreach my $n(1..1e4) {
  221. #method_1($n*3236000768);
  222. #method_1($n* 3236000768);
  223. #method_1($n * 18386368);
  224. # ($n == 1) or gcd($n, $multiplier) > 1 or next;
  225. method_1(mulint($n, $multiplier));
  226. }