417 Reciprocal cycles II.jl 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/julia
  2. # Daniel "Trizen" Șuteu
  3. # Date: 16 November 2021
  4. # https://github.com/trizen
  5. # Reciprocal cycles II
  6. # https://projecteuler.net/problem=417
  7. # Runtime: 9 minutes, 12 seconds
  8. # Simple solution, by removing any divisibility by 2 and 5 from n, then:
  9. # L(n) = znorder(10, n)
  10. # Optimization: iterate over the odd integers k and ingore multiples of 5.
  11. using Primes
  12. function divisors(n)
  13. d = Int64[1]
  14. for (p,e) in factor(n)
  15. t = Int64[]
  16. r = 1
  17. for i in 1:e
  18. r *= p
  19. for u in d
  20. push!(t, u*r)
  21. end
  22. end
  23. append!(d, t)
  24. end
  25. return sort(d)
  26. end
  27. function znorder(a, n)
  28. if isprime(n)
  29. for d in divisors(n-1)
  30. if (powermod(a, d, n) == 1)
  31. return d
  32. end
  33. end
  34. end
  35. f = factor(n)
  36. if (length(f) == 1) # is prime power
  37. p = first(first(f))
  38. z = znorder(a, p)
  39. while (powermod(a, z, n) != 1)
  40. z *= p
  41. end
  42. return z
  43. end
  44. pp_orders = Int64[]
  45. for (p,e) in f
  46. push!(pp_orders, znorder(a, p^e))
  47. end
  48. return lcm(pp_orders)
  49. end
  50. function p_417()
  51. total = 0
  52. limit = 100_000_000
  53. for k in 3:2:limit
  54. rem(k, 5) == 0 && continue
  55. smooth = [k]
  56. for p in [2,5]
  57. for n in smooth
  58. if (n*p <= limit)
  59. push!(smooth, n*p)
  60. end
  61. end
  62. end
  63. total += length(smooth) * znorder(10, k)
  64. end
  65. return total
  66. end
  67. println(p_417())