smooth_generate.pl 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #!/usr/bin/perl
  2. # Smallest number m such that tau(k) * k = m has exactly n solutions when tau(k) is the number of divisors of k.
  3. # https://oeis.org/A338381
  4. # a(6) <= 1508867287200000
  5. # a(7) <= 33195080318400000
  6. # a(8) <= 12938292961651375718400
  7. # a(8) <= 2544150895374925200000
  8. # a(9) <= 55487699012097891000000
  9. # a(6) <= 1508867287200000, a(8) <= 2544150895374925200000, a(9) <= 55487699012097891000000. - ~~~~
  10. use 5.020;
  11. use warnings;
  12. use experimental qw(signatures);
  13. use Math::GMPz;
  14. use ntheory qw(:all);
  15. #~ use Math::AnyNum qw(:overload);
  16. sub check_valuation ($n, $p) {
  17. 1
  18. #~ if ($p == 2) {
  19. #~ return valuation($n, $p) < 20;
  20. #~ }
  21. #~ if ($p == 3) {
  22. #~ return valuation($n, $p) < 20;
  23. #~ }
  24. #~ if ($p == 5) {
  25. #~ return valuation($n, $p) < 10;
  26. #~ }
  27. #~ if ($p == 7) {
  28. #~ return valuation($n, $p) < 10;
  29. #~ }
  30. #~ if ($p == 11 or $p == 13) {
  31. #~ return valuation($n, $p) < 10;
  32. #~ }
  33. #~ if ($p == 17 or $p == 19) {
  34. #~ return valuation($n, $p) < 3;
  35. #~ }
  36. #~ ($n % $p) != 0;
  37. }
  38. sub smooth_numbers ($limit, $primes) {
  39. my @h = (1);
  40. foreach my $p (@$primes) {
  41. say "Prime: $p";
  42. foreach my $n (@h) {
  43. if ($n * $p < $limit and check_valuation($n, $p)) {
  44. push @h, mulint($n, $p);
  45. }
  46. }
  47. }
  48. return \@h;
  49. }
  50. #
  51. # Example for finding numbers `m` such that:
  52. # sigma(m) * phi(m) = n^k
  53. # for some `n` and `k`, with `n > 1` and `k > 1`.
  54. #
  55. # See also: https://oeis.org/A306724
  56. #
  57. sub isok ($n) {
  58. my $count = 0;
  59. #map { divisor_sum($_, 0) * $_ == } divisors($n)
  60. foreach my $d(divisors($n)) {
  61. if (mulint(scalar(divisors($d)), $d) == $n) {
  62. ++$count;
  63. }
  64. }
  65. $count;
  66. }
  67. my @smooth_primes;
  68. foreach my $p (@{primes(4801)}) {
  69. if ($p == 2) {
  70. push @smooth_primes, $p;
  71. next;
  72. }
  73. my @f1 = factor($p - 1);
  74. my @f2 = factor($p + 1);
  75. if ($f1[-1] <= 7 and $f2[-1] <= 7) {
  76. push @smooth_primes, $p;
  77. }
  78. }
  79. my $h = smooth_numbers((~0)*10, [sort {$a <=> $b} (
  80. #19, 3, 13, 11, 2, 7, 17, 5
  81. #13, 3, 19, 7, 2, 11, 17, 5
  82. #5, 13, 2, 17, 11, 3, 7, 19, 23, 31, 43, 41, 37
  83. @{primes(13)}
  84. )]);
  85. say "\nFound: ", scalar(@$h), " terms";
  86. my %table;
  87. @$h = sort {$a<=> $b} @$h;
  88. foreach my $n(@$h) {
  89. ($n%2) == 0 or next;
  90. #valuation($n, 2) >= 5 or next;
  91. #~ valuation($n, 3) >= 5 or next;
  92. my $k = mulint($n, scalar(divisors($n)));
  93. push @{$table{$k}}, $n;
  94. if (scalar(@{$table{$k}}) >= 6) {
  95. my $p = isok($k);
  96. say "[$p] Found: $k";
  97. if ($p == 6 and $k < 1508867287200000) {
  98. die "Found a smaller bound for a($p) -> $k";
  99. }
  100. if ($p == 7 and $k < 33195080318400000) {
  101. die "Found a smaller bound for a($p) -> $k";
  102. }
  103. if ($p == 8 and $k < "2544150895374925200000") {
  104. die "Found a smaller bound for a($p) -> $k";
  105. }
  106. if ($p == 9 and $k < "55487699012097891000000") {
  107. die "Found a smaller bound for a($p) -> $k";
  108. }
  109. if ($p > 9) {
  110. die "Found a new upper-bound for a($p) -> $k";
  111. }
  112. }
  113. }
  114. __END__
  115. @$h = sort { $a <=> $b } @$h;
  116. foreach my $n (@$h) {
  117. #next if ($n < 12134385235627200000);
  118. #next if ($n < 3231993729182400000);
  119. ($n % 10) == 0 or next;
  120. #($n % 23) == 0 or next;
  121. valuation($n, 2) >= 7 or next;
  122. valuation($n, 3) >= 3 or next;
  123. valuation($n, 5) >= 3 or next;
  124. #Math::AnyNum::is_smooth($n, 19) && next;
  125. #say "Testing: $n";
  126. my $p = isok($n);
  127. if ($p >= 6) {
  128. say "[$p] Testing: $n";
  129. if ($p >= 8) {
  130. die "a($p) <= $n";
  131. }
  132. #say "a($p) = $n -> ", join(' * ', map { "$_->[0]^$_->[1]" } factor_exp($n));
  133. #push @{$table{$p}}, $n;
  134. }
  135. }
  136. say '';
  137. foreach my $k (sort { $a <=> $b } keys %table) {
  138. say "a($k) <= ", vecmin(@{$table{$k}});
  139. }