smooth.pl 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 06 March 2019
  4. # https://github.com/trizen
  5. # Generalized algorithm for generating numbers that are smooth over a set A of primes, bellow a given limit.
  6. #~ var a = [1729, 46657, 2433601, 2628073, 19683001, 67371265, 110592000001, 351596817937, 422240040001, 432081216001, 2116874304001, 3176523000001, 18677955240001, 458631349862401, 286245437364810001, 312328165704192001, 12062716067698821000001, 211215936967181638848001, 411354705193473163968001, 14295706553536348081491001, 32490089562753934948660824001, 782293837499544845175052968001, 611009032634107957276386802479001]
  7. #~ say a.map{.dec.icbrt.factor_exp.grep{_[1] > 1}.grep{_[0] == 1828399}}
  8. # [2,4]
  9. # [3,3]
  10. # [5,2]
  11. # [11,2]
  12. # [17,2]
  13. # 2, 3, 5, 7, 11, 13, 17, 19, 23, 31, 37, 43, 53, 67, 83, 107, 131, 163, 181, 257, 263, 2837, 53129, 1828399
  14. use 5.020;
  15. use warnings;
  16. use experimental qw(signatures);
  17. use Math::GMPz;
  18. use ntheory qw(:all);
  19. sub check_valuation ($n, $p) {
  20. if ($p == 2) {
  21. return valuation($n, $p) < 4;
  22. }
  23. if ($p == 3) {
  24. return valuation($n, $p) < 3;
  25. }
  26. if ($p == 5) {
  27. return valuation($n, $p) < 2;
  28. }
  29. if ($p == 11) {
  30. return valuation($n, $p) < 2;
  31. }
  32. if ($p == 17) {
  33. return valuation($n, $p) < 2;
  34. }
  35. ($n % $p) != 0;
  36. }
  37. sub smooth_numbers ($limit, $primes) {
  38. my @h = (1);
  39. foreach my $p (@$primes) {
  40. say "Prime: $p";
  41. foreach my $n (@h) {
  42. if ($n * $p <= $limit and check_valuation($n, $p)) {
  43. push @h, $n * $p;
  44. }
  45. }
  46. }
  47. return \@h;
  48. }
  49. my $z = Math::GMPz::Rmpz_init();
  50. my $t2 = Math::GMPz::Rmpz_init_set_str("286245437364810001", 10);
  51. my $t3 = Math::GMPz::Rmpz_init_set_str("611009032634107957276386802479001", 10);
  52. sub isok ($n) {
  53. $n % 2 == 0 or return;
  54. #return if ($n <= 84855997590);
  55. foreach my $k(2..3) {
  56. Math::GMPz::Rmpz_ui_pow_ui($z, $n, $k);
  57. Math::GMPz::Rmpz_add_ui($z, $z, 1);
  58. #Math::GMPz::Rmpz_fits_ulong_p($z) && return;
  59. is_pseudoprime($z, 2) || next;
  60. is_prime($z) && next;
  61. if (is_carmichael($z)) {
  62. if ($k == 3 and Math::GMPz::Rmpz_cmp($z, $t3) > 0) {
  63. die "New term found: a^3+1 = $z";
  64. }
  65. if ($k == 2 and Math::GMPz::Rmpz_cmp($z, $t2) > 0) {
  66. die "New term found: a^2 + 1 = $z";
  67. }
  68. return $z;
  69. }
  70. }
  71. undef;
  72. }
  73. my @smooth_primes;
  74. #@smooth_primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 31, 37, 43, 53, 67, 83, 107, 131, 163, 181, 257, 263, 2837, 53129, 1828399);
  75. #@smooth_primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 31, 37, 43, 53, 67, 83);
  76. #@smooth_primes = @{primes(100)};
  77. @smooth_primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 31, 37, 43, 67, 83, 107, 131, 163, 257, 263, 2837, 53129, 1828399);
  78. my $h = smooth_numbers(84855997590, \@smooth_primes);
  79. say "\nFound: ", scalar(@$h), " terms";
  80. my %seen;
  81. my @primes = @{primes(1e4,2e6)};
  82. foreach my $n (sort {$a <=> $b} @$h) {
  83. #~ say "Testing: $n";
  84. #~ next if ($n <= 1e6);
  85. #~ if ($n%2 == 0) {
  86. #~ forprimes {
  87. #~ my $p = $_;
  88. #~ if (defined(my $z = isok($n*$p))) {
  89. #~ say "$n*$p -> $z" if !$seen{$z}++;
  90. #~ sleep 3;
  91. #~ }
  92. #~ } int(84855997590 / $n), 3e5;
  93. #~ }
  94. #~ if ($n%2 == 0) {
  95. #~ foreach my $k(int(84855997590/$n)..3e5) {
  96. #~ if (defined(my $z = isok($n*$k))) {
  97. #~ say "$n*$k -> $z" if !$seen{$z}++;
  98. #~ sleep 3;
  99. #~ }
  100. #~ }
  101. #~ }
  102. if(defined(my $z = isok($n))) {
  103. say "$n -> $z";
  104. }
  105. }
  106. __END__
  107. 12 -> 1729
  108. 36 -> 46657
  109. 138 -> 2628073
  110. 216 -> 46657
  111. 270 -> 19683001
  112. 1560 -> 2433601
  113. 7560 -> 432081216001
  114. 8208 -> 67371265
  115. 12840 -> 2116874304001
  116. 678480 -> 312328165704192001
  117. 22934100 -> 12062716067698821000001
  118. 59553720 -> 211215936967181638848001
  119. 74371320 -> 411354705193473163968001
  120. 242699310 -> 14295706553536348081491001
  121. 3190927740 -> 32490089562753934948660824001
  122. 9214178820 -> 782293837499544845175052968001
  123. 84855997590 -> 611009032634107957276386802479001