ZLA
AST

Problem 26 - Reciprocal Cycles

Project Euler
Post Image
March 12, 2024
Read Time: 3 min

Problem

This problem comes from Project Euler 26

Problem

A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 20 to 10 are given:

1/2 = 0.5
1/3 = 0.(3)
1/4 = 0.25
1/5 = 0.2
1/6 = 0.1(6)
1/7 = 0.(142857)
1/8 = 0.125
1/9 = 0.(1)
1/10 = 0.1

Where 0.1(6) means 0.166666…, and has a 1-digit recurring cycle. In can be seen that 1/7 has a 6-digit recurring cycle.

Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.

Solution

This solution involved a bit of research, but here are three Wikipedia pages that I found helpful: Full Reptend Primes, Multiplicative Order, and Cyclic Number.

Here are the important bits from those pages:

From Full Reptend Primes:

In number theory, a full reptend prime … in base b b is an odd prime number p p such that the Fermat Quotient

qp(b)=bp11pq_p(b) = \dfrac{b^{p-1} -1}{p}

gives a cyclic number.

The cyclic number corresponding to prime p p will possess p1 p -1 digits if and only if p p is a full reptend prime. That is, the multiplicative order ordp(b)=p1 \text{ord}_p(b) = p - 1

From Multiplicative Order:

In number theory, given a positive integer n n and an integer a a coprime to n n, the multiplicative order of a modulo n n is the smallest positive integer k k such that ak1(mod n) a^k \equiv 1 (\text{mod } n) .

The order of a modulo n n is sometimes written as ordn(a) \text{ord}_n(a)

We can see from the Full Reptend Primes quote that we can generate cyclic numbers that will have p1 p - 1 digits if and only if p p is a full reptend prime.

For example, if the prime number 17 is a full reptend prime (which it is), then it will create a cyclic number with 16 repeating digits!

We check if a prime number is a full reptend prime by checking its multiplicative order. Combining some of the equations and information we have, we get

ordp(10)=1  (mod p) \text{ord}_p(10) = 1 \texttt{\char32\char32} \text{(mod }p)

Or more simply

10k=1  (mod p) 10^k = 1 \texttt{\char32\char32} \text{(mod }p)

Note that

  • Our base b b is 10 and,
  • that k k is some integer, whose range we’ll set between 1 and p p

From the Full Reptend Primes quote, if k=p1 k = p-1, then the prime is full reptend and therefore cyclic.

Code

# Project Euler: Problem 26
# Reciprocal cycles

from PEF import soe

def full_reptend_check(p) -> bool:
    for k in range(1, p):
        if (10**k) % p == 1:
            if k == p-1:
                return True
            else:
                return False

primes = soe(1000)
for p in reversed(primes):
    if(full_reptend_check(p)):
        print(p)
        break

The program carries out what was discussed in the Solution. The function full_reptend_check() finds if a prime is a full reptend prime and returns True if it is.

One thing of note is that I check for full reptend primes in reverse, starting from the largest prime. The reason is pretty simple: If a prime is full reptend, then the cyclic number is p1 p-1 digits long, so it’s faster to check starting from the largest number.