carmichael_overpseudoprimes_cached.pl 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #!/usr/bin/perl
  2. # Carmichael numbers (A002997) that are also overpseudoprimes to base 2 (A141232).
  3. # https://oeis.org/A352987
  4. # First terms of the sequence:
  5. # 65700513721, 168003672409, 459814831561, 13685652197857, 34477679139751, 74031531351121, 92327722290241, 206175669172201, 704077371354601, 1882982959757929, 2901482064497017, 3715607011189609, 5516564718607489, 5636724028491697, 6137426373439681, 14987802403246609
  6. # Let a(n) be the smallest Carmichael number with n prime factors that is also an overpseudoprime to base 2.
  7. # a(3) = 65700513721
  8. # a(4) <= 84286331493236478328609
  9. # a(5) <= 3157343757823970959759947380425728583752001
  10. # Note: all overpseudoprimes to base 2, are also super-pseudoprimes to base 2 (A050217).
  11. # Subsequence of: A291637
  12. # Inspired by:
  13. # https://oeis.org/A291637
  14. # https://oeis.org/A063847
  15. use 5.020;
  16. use strict;
  17. use warnings;
  18. use Storable;
  19. use Math::GMPz;
  20. use ntheory qw(:all);
  21. #use Math::Sidef qw(is_over_psp);
  22. use Math::Prime::Util::GMP;
  23. use experimental qw(signatures);
  24. my $carmichael_file = "cache/factors-carmichael.storable";
  25. my $super_psp_file = "cache/factors-superpsp.storable";
  26. my $carmichael = retrieve($carmichael_file);
  27. my $super_psp = retrieve($super_psp_file);
  28. sub is_over_pseudoprime_fast ($n, $factors) {
  29. Math::Prime::Util::GMP::is_strong_pseudoprime($n, 2) || return;
  30. my $gcd = Math::Prime::Util::GMP::gcd(map { ($_ < ~0) ? ($_ - 1) : Math::Prime::Util::GMP::subint($_, 1) } @$factors);
  31. Math::Prime::Util::GMP::powmod(2, $gcd, $n) eq '1'
  32. or return;
  33. my $prev;
  34. foreach my $p (@$factors) {
  35. if (defined($prev)) {
  36. if ($p < ~0) {
  37. Math::Prime::Util::powmod(2, $prev, $p) == 1 or return;
  38. }
  39. else {
  40. Math::Prime::Util::GMP::powmod(2, $prev, $p) eq '1' or return;
  41. }
  42. }
  43. my $zn = znorder(2, $p);
  44. if (defined($prev)) {
  45. $zn == $prev or return;
  46. }
  47. else {
  48. $prev = $zn;
  49. }
  50. }
  51. return 1;
  52. }
  53. my %table;
  54. foreach my $n (sort { $a <=> $b } map { Math::GMPz->new($_) } grep { exists $carmichael->{$_} } keys %$super_psp) {
  55. my @factors = split(' ', $super_psp->{$n});
  56. my $count = scalar(@factors);
  57. next if ($count < 4);
  58. #is_over_psp($n) || next;
  59. is_over_pseudoprime_fast($n, \@factors) || next;
  60. next if (exists $table{$count});
  61. $table{$count} = $n;
  62. }
  63. foreach my $count (sort { $a <=> $b } keys %table) {
  64. say "a($count) <= $table{$count}";
  65. }
  66. __END__
  67. a(4) <= 84286331493236478328609
  68. a(5) <= 3157343757823970959759947380425728583752001
  69. # Old upper-bounds:
  70. a(5) <= 5805231246207180356507676627834704416816321
  71. a(5) <= 3848515708338676403444146123852434164444641