squarefree_almost_prime_divisors.pl 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 29 March 2021
  4. # https://github.com/trizen
  5. # Generate all the squarefree k-almost prime divisors of n.
  6. use 5.020;
  7. use ntheory qw(:all);
  8. use experimental qw(signatures);
  9. sub squarefree_almost_prime_divisors ($n, $k) {
  10. if ($k == 0) {
  11. return (1);
  12. }
  13. my @factor_exp = factor_exp($n);
  14. my @factors = map { $_->[0] } @factor_exp;
  15. my %valuations = map { @$_ } @factor_exp;
  16. my $factors_end = $#factors;
  17. if ($k == 1) {
  18. return @factors;
  19. }
  20. my @list;
  21. sub ($m, $k, $i = 0) {
  22. if ($k == 1) {
  23. my $L = divint($n, $m);
  24. foreach my $j ($i .. $factors_end) {
  25. my $q = $factors[$j];
  26. last if ($q > $L);
  27. push(@list, mulint($m, $q));
  28. }
  29. return;
  30. }
  31. my $L = rootint(divint($n, $m), $k);
  32. foreach my $j ($i .. $factors_end - 1) {
  33. my $q = $factors[$j];
  34. last if ($q > $L);
  35. __SUB__->(mulint($m, $q), $k - 1, $j + 1);
  36. }
  37. }->(1, $k);
  38. sort { $a <=> $b } @list;
  39. }
  40. my $n = vecprod(@{primes(15)});
  41. foreach my $k (0 .. prime_omega($n)) {
  42. my @divisors = squarefree_almost_prime_divisors($n, $k);
  43. printf("%2d-squarefree almost prime divisors of %s: [%s]\n", $k, $n, join(', ', @divisors));
  44. }
  45. __END__
  46. 0-squarefree almost prime divisors of 30030: [1]
  47. 1-squarefree almost prime divisors of 30030: [2, 3, 5, 7, 11, 13]
  48. 2-squarefree almost prime divisors of 30030: [6, 10, 14, 15, 21, 22, 26, 33, 35, 39, 55, 65, 77, 91, 143]
  49. 3-squarefree almost prime divisors of 30030: [30, 42, 66, 70, 78, 105, 110, 130, 154, 165, 182, 195, 231, 273, 286, 385, 429, 455, 715, 1001]
  50. 4-squarefree almost prime divisors of 30030: [210, 330, 390, 462, 546, 770, 858, 910, 1155, 1365, 1430, 2002, 2145, 3003, 5005]
  51. 5-squarefree almost prime divisors of 30030: [2310, 2730, 4290, 6006, 10010, 15015]
  52. 6-squarefree almost prime divisors of 30030: [30030]