401 Sum of squares of divisors -- v2.pl 952 B

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 16 September 2019
  4. # https://github.com/trizen
  5. # https://projecteuler.net/problem=401
  6. # Generalized aglorithm described at:
  7. # https://trizenx.blogspot.com/2018/11/partial-sums-of-arithmetical-functions.html
  8. # Runtime: ~39 seconds.
  9. use 5.010;
  10. use strict;
  11. use integer;
  12. use warnings;
  13. use experimental qw(signatures);
  14. use ntheory qw(sqrtint mulmod divmod addmod);
  15. my $mod = 10**9;
  16. my $lim = 10**15;
  17. sub f ($n) {
  18. divmod(mulmod(mulmod($n, $n + 1, $mod), 2 * $n + 1, $mod), 3, $mod) >> 1;
  19. }
  20. sub sum_of_sum_of_squared_divisors ($n) { # using the "Dirichlet hyperbola method"
  21. my $s = sqrtint($n);
  22. my $total = 0;
  23. for my $k (1 .. $s) {
  24. $total = addmod($total, f(int($n/$k)), $mod);
  25. $total = addmod($total, mulmod($k*$k, int($n/$k), $mod), $mod);
  26. }
  27. $total -= mulmod($s, f($s), $mod);
  28. return $total % $mod;
  29. }
  30. say sum_of_sum_of_squared_divisors($lim);