754 Product of Gauss Factorials -- v2.pl 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. #!/usr/bin/perl
  2. # Product of Gauss Factorials
  3. # https://projecteuler.net/problem=754
  4. # See also:
  5. # https://oeis.org/A001783
  6. # Using the identity:
  7. # g(n) = Prod_{d|n} ((n/d)! * d^(n/d))^moebius(d)
  8. # G(n) = Prod_{d=1..n} Prod_{k=1..floor(n/d)} (k! * d^k)^moebius(d)
  9. # Runtime: ~20 minutes.
  10. use 5.020;
  11. use strict;
  12. use warnings;
  13. use ntheory qw(:all);
  14. use experimental qw(signatures);
  15. sub F ($n, $m) {
  16. say ":: Computing the product of Gaussian factorials...";
  17. my $prod = 1;
  18. forsquarefree {
  19. my $k = $_;
  20. my $nfac = 1;
  21. my $mu = moebius($k);
  22. foreach my $j (1 .. divint($n, $k)) {
  23. $nfac = mulmod($nfac, $j, $m);
  24. $prod = mulmod($prod, powmod(mulmod($nfac, powmod($k, $j, $m), $m), $mu, $m), $m);
  25. }
  26. } $n;
  27. return $prod;
  28. }
  29. use Test::More tests => 6;
  30. is(F(10, next_prime(powint(10, 20))), 23044331520000);
  31. is(F(10, 1_000_000_007), 331358692);
  32. is(F(1e2, 1_000_000_007), 777776709);
  33. is(F(1e3, 1_000_000_007), 297877340);
  34. is(F(1e4, 1_000_000_007), 517055464);
  35. is(F(1e5, 1_000_000_007), 516871211);
  36. #say F(1e3, 1000000007); # takes 0.07s
  37. #say F(1e4, 1000000007); # takes 0.4s
  38. #say F(1e5, 1000000007); # takes 2s
  39. #say F(1e6, 1000000007); # takes 12s
  40. #say F(1e7, 1000000007); # takes ~2 minutes
  41. say "\n:: Computing: G(10^8)";
  42. say F(1e8, 1000000007);