sum_of_primes_generalized.pl 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. #!/usr/bin/perl
  2. # Simple implementation of the prime-summation function:
  3. # Sum_{p prime <= n} p^k, for any fixed k >= 0.
  4. use 5.020;
  5. use warnings;
  6. use experimental qw(signatures);
  7. use Math::GMPz;
  8. use ntheory qw(divint sqrtint);
  9. use Math::Prime::Util::GMP qw(faulhaber_sum);
  10. sub sum_of_primes ($n, $k = 1) {
  11. $n > ~0 and return undef;
  12. $n <= 1 and return 0;
  13. my $r = sqrtint($n);
  14. my @V = map { divint($n, $_) } 1 .. $r;
  15. push @V, CORE::reverse(1 .. $V[-1] - 1);
  16. my $t = Math::GMPz::Rmpz_init_set_ui(0);
  17. my $u = Math::GMPz::Rmpz_init();
  18. my %S;
  19. @S{@V} = map { Math::GMPz::Rmpz_init_set_str(faulhaber_sum($_, $k), 10) } @V;
  20. foreach my $p (2 .. $r) {
  21. if ($S{$p} > $S{$p - 1}) {
  22. my $cp = $S{$p - 1};
  23. my $p2 = $p * $p;
  24. Math::GMPz::Rmpz_ui_pow_ui($t, $p, $k);
  25. foreach my $v (@V) {
  26. last if ($v < $p2);
  27. Math::GMPz::Rmpz_sub($u, $S{divint($v, $p)}, $cp);
  28. Math::GMPz::Rmpz_submul($S{$v}, $u, $t);
  29. }
  30. }
  31. }
  32. $S{$n} - 1;
  33. }
  34. say sum_of_primes(1e8); #=> 279209790387276
  35. say sum_of_primes(1e8, 2); #=> 18433608754948081174274