k-odd-powerful_numbers_in_range.sf 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #!/usr/bin/ruby
  2. # Author: Trizen
  3. # Date: 28 February 2021
  4. # Edit: 23 February 2024
  5. # https://github.com/trizen
  6. # Fast recursive algorithm for generating all the odd k-powerful numbers in a given range [a,b].
  7. # A positive integer n is considered k-powerful, if for every prime p that divides n, so does p^k.
  8. # Example:
  9. # 2-powerful = a^2 * b^3, for a,b >= 1
  10. # 3-powerful = a^3 * b^4 * c^5, for a,b,c >= 1
  11. # 4-powerful = a^4 * b^5 * c^6 * d^7, for a,b,c,d >= 1
  12. # See also:
  13. # https://oeis.org/A062739
  14. func odd_powerful_numbers(A, B, k=2) {
  15. var odd_powerful = []
  16. func (m,r) {
  17. var from = 1
  18. var upto = iroot(idiv(B, m), r)
  19. if (r <= k) {
  20. if (A > m) {
  21. # Optimization by Dana Jacobsen (from Math::Prime::Util::PP)
  22. with (idiv_ceil(A,m)) {|l|
  23. if ((l >> r) == 0) {
  24. from = 2
  25. }
  26. else {
  27. from = l.iroot(r)
  28. from++ if (ipow(from, r) != l)
  29. }
  30. }
  31. }
  32. return nil if (from > upto)
  33. for j in (from .. upto) {
  34. odd_powerful << (m * ipow(j, r)) if j.is_odd
  35. }
  36. return nil
  37. }
  38. for j in (from .. upto) {
  39. j.is_even && next
  40. j.is_coprime(m) || next
  41. j.is_squarefree || next
  42. __FUNC__(m * ipow(j, r), r-1)
  43. }
  44. }(1, 2*k - 1)
  45. odd_powerful.sort
  46. }
  47. var a = 1e5.irand
  48. var b = 1e7.irand
  49. for k in (2..5) {
  50. say "Testing: k = #{k}"
  51. assert_eq(
  52. odd_powerful_numbers(a, b, k),
  53. k.powerful(a, b).grep{.is_odd}
  54. )
  55. }
  56. say odd_powerful_numbers(1e6 - 2e4, 1e6, 2) #=> [982081, 984987, 985527, 986049, 990025, 990125, 994009, 998001]