partial_sums_of_jordan_totient_function.sf 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #!/usr/bin/ruby
  2. # Author: Daniel "Trizen" Șuteu
  3. # Date: 21 November 2018
  4. # https://github.com/trizen
  5. # A new algorithm for computing the partial-sums of the Jordan totient function `J_m(k)`, for `1 <= k <= n`:
  6. #
  7. # Sum_{k=1..n} J_m(k)
  8. #
  9. # for any fixed integer m >= 1.
  10. # Based on the formula:
  11. # Sum_{k=1..n} J_m(k) = Sum_{k=1..n} moebius(k) * F(m, floor(n/k))
  12. #
  13. # where F(n,x) is Faulhaber's formula for `Sum_{k=1..x} k^n`, defined in terms of Bernoulli polynomials as:
  14. # F(n,x) = (Bernoulli(n+1, x+1) - Bernoulli(n+1, 1)) / (n+1)
  15. # Example for a(n) = Sum_{k=1..n} J_2(k):
  16. # a(10^1) = 312
  17. # a(10^2) = 280608
  18. # a(10^3) = 277652904
  19. # a(10^4) = 277335915120
  20. # a(10^5) = 277305865353048
  21. # a(10^6) = 277302780859485648
  22. # a(10^7) = 277302491422450102032
  23. # a(10^8) = 277302460845902192282712
  24. # a(10^9) = 277302457878113251222146576
  25. # Asymptotic formula:
  26. # n^3 / (3*zeta(3)) ~ Sum_{k=1..n} J_2(k)
  27. # In general, for m>=1:
  28. # n^(m+1) / ((m+1) * zeta(m+1)) ~ Sum_{k=1..n} J_m(k)
  29. # See also:
  30. # https://oeis.org/A321879
  31. # https://en.wikipedia.org/wiki/Mertens_function
  32. # https://en.wikipedia.org/wiki/M%C3%B6bius_function
  33. # https://en.wikipedia.org/wiki/Jordan%27s_totient_function
  34. # https://trizenx.blogspot.com/2018/08/interesting-formulas-and-exercises-in.html
  35. func jordan_totient_partial_sum (n, m) { # O(sqrt(n)) complexity
  36. var total = 0
  37. var s = n.isqrt
  38. var u = int(n/(s+1))
  39. for k in (1..s) {
  40. total += (mertens(int(n/(k+1))+1, int(n/k)) * faulhaber_sum(k, m))
  41. }
  42. moebius(0, u).each_kv { |k,v|
  43. total += (v * faulhaber_sum(int(n/k), m)) if v
  44. }
  45. return total
  46. }
  47. func jordan_totient_partial_sum_2 (n, m) { # O(sqrt(n)) complexity
  48. var total = 0
  49. var s = n.isqrt
  50. for k in (1..s) {
  51. total += (moebius(k) * faulhaber_sum(floor(n/k), m))
  52. total += (k**m * mertens(floor(n/k)))
  53. }
  54. total -= mertens(s)*faulhaber_sum(s, m)
  55. return total
  56. }
  57. func jordan_totient_partial_sum_test (n, m) { # just for testing
  58. 1..n -> sum {|k| jordan_totient(k, m) }
  59. }
  60. for m in (0 .. 10) {
  61. var n = 10000.irand
  62. var t1 = jordan_totient_partial_sum(n, m)
  63. var t2 = jordan_totient_partial_sum_2(n, m)
  64. var t3 = jordan_totient_partial_sum_test(n, m)
  65. assert_eq(t1, t2)
  66. assert_eq(t1, t3)
  67. say "Sum_{k=1..#{n}} J_#{m}(k) = #{t1}"
  68. }
  69. __END__
  70. Sum_{k=1..1970} J_0(k) = 1
  71. Sum_{k=1..4807} J_1(k) = 7025920
  72. Sum_{k=1..7884} J_2(k) = 135913559688
  73. Sum_{k=1..7682} J_3(k) = 804616377756508
  74. Sum_{k=1..8242} J_4(k) = 7337902692248665200
  75. Sum_{k=1..8522} J_5(k) = 62774227223853599101840
  76. Sum_{k=1..1838} J_6(k) = 10058436011292984094248
  77. Sum_{k=1..4235} J_7(k) = 12893831794819045373033950546
  78. Sum_{k=1..7851} J_8(k) = 12573618726179583880817452889027520
  79. Sum_{k=1..8716} J_9(k) = 252923600785652984962297725675542659970
  80. Sum_{k=1..2325} J_10(k) = 977400706925586857534627653563936624