erdos_generate_fibonacci_from_lambdas.pl 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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. # This version generates Fibonacci pseudoprimes and other Lucas pseudoprimes.
  9. use 5.020;
  10. use warnings;
  11. use ntheory qw(:all);
  12. use List::Util qw(shuffle uniq);
  13. use experimental qw(signatures);
  14. # Modular product of a list of integers
  15. sub vecprodmod ($arr, $mod) {
  16. my $prod = 1;
  17. foreach my $k (@$arr) {
  18. $prod = mulmod($prod, $k, $mod);
  19. }
  20. $prod;
  21. }
  22. # Primes p such that p-1 divides L and p does not divide L
  23. #~ sub lambda_primes ($L) {
  24. #~ grep { ($L % $_) != 0 } grep { $_ > 2 and is_prime($_) } map { $_ + 1 } divisors($L);
  25. #~ }
  26. sub lambda_primes ($L) {
  27. my @D = divisors($L);
  28. #my $D = 19; # 5, -7, 9, -11, 13, -15, 17, -19, 21
  29. my $D = 5; # 5, 12, 21, 32, 45, 60, 77, 96
  30. uniq(
  31. #~ (grep { ($_ > 2) && ($L % $_ != 0) && is_prime($_) && ($L % ($_ - kronecker(5, $_)) == 0) } map { $_ - 1 } @D),
  32. #~ (grep { ($_ > 2) && ($L % $_ != 0) && is_prime($_) && ($L % ($_ + kronecker(5, $_)) == 0) } map { $_ + 1 } @D)
  33. #~ (grep { ($_ > 2) and ($L % $_ != 0) and kronecker($D, $_) == -1 and ($L % ($_ - kronecker($D, $_)) == 0) and is_smooth($_-1, 1e2) } map { $_ + 1 } grep { is_prime($_+1) } @D),
  34. #~ (grep { ($_ > 2) and ($L % $_ != 0) and kronecker($D, $_) == -1 and ($L % ($_ - kronecker($D, $_)) == 0) and is_smooth($_-1, 1e2) } map { $_ - 1 } grep { is_prime($_-1) } @D)
  35. #~ (grep { ($_ > 2) and ($L % $_ != 0) and kronecker($D, $_) == -1 and ($L % ($_ - kronecker($D, $_)) == 0) and is_smooth($_-1, (factor($_+1))[-1]) } map { $_ + 1 } grep { is_prime($_+1) } @D),
  36. #~ (grep { ($_ > 2) and ($L % $_ != 0) and kronecker($D, $_) == -1 and ($L % ($_ - kronecker($D, $_)) == 0) and is_smooth($_-1, (factor($_+1))[-1]) } map { $_ - 1 } grep { is_prime($_-1) } @D)
  37. (grep { ($_ > 2) and ($L % $_ != 0) and (kronecker($D, $_) == -1) and ($L % ($_ - kronecker($D, $_)) == 0) } map { $_ + 1 } grep { is_prime($_+1) } @D),
  38. (grep { ($_ > 2) and ($L % $_ != 0) and (kronecker($D, $_) == -1) and ($L % ($_ - kronecker($D, $_)) == 0) } map { $_ - 1 } grep { is_prime($_-1) } @D)
  39. );
  40. }
  41. sub method_1 ($L) { # smallest numbers first
  42. my @P = lambda_primes($L);
  43. my $n = scalar(@P);
  44. my @orig = @P;
  45. my $max = 1e4;
  46. my $max_k = 30;
  47. foreach my $k (3 .. @P>>1) {
  48. #next if (binomial($n, $k) > 1e6);
  49. next if ($k > $max_k);
  50. @P = @orig;
  51. my $count = 0;
  52. forcomb {
  53. if (vecprodmod([@P[@_]], $L) == 1) {
  54. say vecprod(@P[@_]);
  55. }
  56. lastfor if (++$count > $max);
  57. } $n, $k;
  58. next if (binomial($n, $k) < $max);
  59. @P = reverse(@P);
  60. $count = 0;
  61. forcomb {
  62. if (vecprodmod([@P[@_]], $L) == 1) {
  63. say vecprod(@P[@_]);
  64. }
  65. lastfor if (++$count > $max);
  66. } $n, $k;
  67. @P = shuffle(@P);
  68. $count = 0;
  69. forcomb {
  70. if (vecprodmod([@P[@_]], $L) == 1) {
  71. say vecprod(@P[@_]);
  72. }
  73. lastfor if (++$count > $max);
  74. } $n, $k;
  75. }
  76. my $B = $L-vecprodmod(\@P, $L);
  77. my $T = vecprod(@P);
  78. foreach my $k (2 .. @P>>1) {
  79. #next if (binomial($n, $k) > 1e6);
  80. last if ($k > $max_k);
  81. @P = @orig;
  82. my $count = 0;
  83. forcomb {
  84. if (vecprodmod([@P[@_]], $L) == $B) {
  85. my $S = vecprod(@P[@_]);
  86. say ($T / $S) if ($T != $S);
  87. }
  88. lastfor if (++$count > $max);
  89. } $n, $k;
  90. next if (binomial($n, $k) < $max);
  91. @P = reverse(@P);
  92. $count = 0;
  93. forcomb {
  94. if (vecprodmod([@P[@_]], $L) == $B) {
  95. my $S = vecprod(@P[@_]);
  96. say ($T / $S) if ($T != $S);
  97. }
  98. lastfor if (++$count > $max);
  99. } $n, $k;
  100. @P = shuffle(@P);
  101. $count = 0;
  102. forcomb {
  103. if (vecprodmod([@P[@_]], $L) == $B) {
  104. my $S = vecprod(@P[@_]);
  105. say ($T / $S) if ($T != $S);
  106. }
  107. lastfor if (++$count > $max);
  108. } $n, $k;
  109. }
  110. }
  111. while (<>) {
  112. #next if $_ < 1e4;
  113. chomp;
  114. #next if $_ < 49904316;
  115. method_1($_);
  116. }
  117. __END__
  118. foreach my $L(
  119. #2..5e3
  120. #80, 120, 144, 2520, 5760, 6480, 7920, 15120, 30240, 94248, 110880, 285120, 597168, 604800, 1441440, 1663200, 1738800, 2217600, 5216400, 13305600, 43243200, 64864800, 648648000, 4034016000, 8951342400, 12070749600, 67541947200
  121. #24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260, 1680, 2520, 5040, 7560, 10080, 15120, 20160, 25200, 27720, 45360, 50400, 55440, 83160, 110880, 166320, 221760, 277200, 332640, 498960, 554400, 665280, 720720, 1081080, 1441440, 2162160
  122. #10080, 15120, 20160, 25200, 27720, 45360, 50400, 55440, 83160, 110880, 166320, 221760, 277200, 332640, 498960, 554400, 665280, 720720, 1081080, 1441440, 2162160, 2882880, 3603600, 4324320, 6486480, 7207200, 8648640, 10810800, 14414400, 17297280, 21621600, 32432400, 36756720, 43243200, 61261200, 73513440, 110270160, 122522400, 147026880, 183783600, 245044800, 294053760, 367567200, 551350800, 698377680, 735134400, 1102701600, 1396755360, 2095133040, 2205403200, 2327925600, 2793510720, 3491888400, 4655851200, 5587021440, 6983776800, 10475665200, 13967553600, 20951330400, 27935107200, 41902660800, 48886437600, 64250746560, 73329656400, 80313433200, 97772875200, 128501493120, 146659312800, 160626866400, 240940299600, 293318625600, 321253732800, 481880599200, 642507465600, 963761198400, 1124388064800, 1606268664000, 1686582097200, 1927522396800, 2248776129600, 3212537328000, 3373164194400, 4497552259200, 6746328388800, 8995104518400, 9316358251200
  123. #34082048, 64352288, 73545472, 128704576, 147090944, 257409152, 294181888, 374902528, 514818304, 1176727552, 1231886656, 2059273216
  124. #11531520, 80720640, 126846720, 149909760, 329801472, 887927040, 1049368320, 1233872640, 1649007360, 2410087680, 11543051520, 16040344320, 31331139840, 40971490560, 48420852480, 106525875456, 219317978880, 286800433920, 473034481920, 532629377280, 745681128192, 3728405640960, 3979054759680, 5203379301120, 6149448264960, 67643930914560, 473507516401920
  125. #144144, 720720, 1585584, 2306304, 15135120, 25369344, 31279248, 157549392, 1049368320, 1233872640, 1533692160, 1815061248, 2048142096, 6146300160
  126. #5040, 7560, 10080, 21420, 57960, 59616, 109200, 110160, 163800, 178020, 308448, 540540, 811440, 3908520, 7592400, 304045280
  127. #3780, 4032, 5040, 10080, 22176, 37800, 75600, 648000
  128. #73545472, 128704576, 147090944, 202250048, 257409152, 294181888, 374902528, 514818304, 1029636608, 1231886656
  129. #2130128, 2434432, 2818816, 3587584, 4260256, 4868864, 8520512, 10506496, 18386368, 19731712, 34082048, 36644608, 36772736, 53557504, 57209152, 63295232, 73545472, 87030944, 128704576, 147090944, 174061888, 202250048, 294181888, 348123776, 374902528, 618345728
  130. #73545472, 128704576, 147090944, 202250048, 257409152, 294181888, 374902528, 514818304, 1029636608, 1231886656
  131. #5040, 75600, 5040, 3780, 37800, 4032, 10080, 22176, 648000
  132. #1240624, 2626624, 7771456, 10506496, 15542912, 139678448
  133. #map{ $_ * 16 } 1188, 2024, 285824, 5789168, 7201568, 15542912, 4352299952
  134. #map { $_ * 7 } (2130128, 2434432, 2818816, 3587584, 4260256, 4868864, 8520512, 10506496, 18386368, 19731712, 34082048, 36644608, 36772736, 53557504, 57209152, 63295232, 73545472, 87030944, 128704576, 147090944, 174061888, 202250048, 257409152, 294181888, 348123776, 374902528, 514818304, 618345728, 1029636608, 1231886656)
  135. #divisors(2237587312658553856)
  136. #285824, 655424, 1350272, 2618528, 2700544, 5789168, 7201568, 15542912, 34105456, 127359232, 251075968, 1426704224, 4352299952, 83510730688, 1189651277584, 38988702524464
  137. #285824, 655424, 1350272, 2618528, 2700544, 5789168, 7201568, 15542912, 34105456, 127359232, 251075968, 1426704224, 4352299952, 83510730688, 1189651277584, 38988702524464
  138. #(4352299952 * 32)
  139. #655424 * 2
  140. #2024, 1188, 7201568, 15542912, 285824, 5789168, 4352299952
  141. ) {
  142. method_1($L);
  143. #method_2($L);
  144. }