549 Divisibility of factorials.pl 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # License: GPLv3
  4. # Date: 17 September 2016
  5. # Website: https://github.com/trizen
  6. # https://projecteuler.net/problem=549
  7. # Runtime: 6 min 33.61s
  8. use utf8;
  9. use 5.010;
  10. use strict;
  11. use integer;
  12. use ntheory qw(
  13. vecmax
  14. vecsum
  15. is_prime
  16. factorial
  17. sum_primes
  18. factor_exp
  19. forcomposites
  20. );
  21. my $limit = 10**8;
  22. my %cache;
  23. sub smarandache {
  24. my ($n) = @_;
  25. return $n if is_prime($n);
  26. my @f = factor_exp($n);
  27. my $Ω = vecsum(map { $_->[1] } @f);
  28. (@f == $Ω)
  29. && return $f[-1][0];
  30. if (@f == 1) {
  31. my $ϕ = $f[0][0];
  32. ($Ω <= $ϕ)
  33. && return $ϕ * $Ω;
  34. exists($cache{$n})
  35. && return $cache{$n};
  36. my $m = $ϕ * $Ω;
  37. my $f = factorial($m - $ϕ);
  38. while ($f % $n == 0) {
  39. $m -= $ϕ;
  40. $f /= $m;
  41. }
  42. return ($cache{$n} = $m);
  43. }
  44. vecmax(map {
  45. $_->[1] == 1 ? $_->[0]
  46. : smarandache($_->[0]**$_->[1])
  47. } @f);
  48. }
  49. my $sum = 0;
  50. forcomposites {
  51. $sum += smarandache($_);
  52. } $limit;
  53. $sum += sum_primes($limit);
  54. say $sum;