Problem Analysis
When you carry out long division to express the unit fraction 1/d as a decimal, the digits after the point either terminate or eventually fall into a repeating loop. The fraction terminates exactly when d's only prime factors are 2 and 5 - the prime factors of our base, 10. For every other d, the expansion settles into a purely repeating cycle, and the length of that cycle is a well-studied number-theoretic quantity called the multiplicative order of 10 modulo d. The multiplicative order of a base a modulo n is the smallest positive integer k such that a^k is congruent to 1 modulo n - written a^k = 1 (mod n). It exists if and only if a and n are coprime (their greatest common divisor is 1). The reason this maps onto our problem is that the remainders produced during long division of 1/d are precisely the sequence 10^k mod d, and the cycle closes the first time that remainder returns to its starting value of 1.
The observation that makes the search efficient is a bound on how long a cycle can be. The remainders in the long-division process are all in the range 1 to d-1, so the cycle length can be at most d-1. When d is prime, Fermat's little theorem tells us the order divides d-1, and the maximum achievable is exactly d-1. This means the longest cycle below a limit L must come from a large d near L, because a small d simply cannot produce a long enough cycle. I exploit this by scanning the top of the range downward rather than testing every d from 2 upward. Computing the order by direct simulation costs O(d) per candidate, and restricting the scan to the top tenth of the range makes the whole search O(L/10 * L) - trivially fast for L = 1000.
Solution Approach
Multiplicative-Order Search by Simulation (Python and C)
Both files implement the same algorithm in two languages. The heart of it is multiplicative_order(a, modulus): I start with a remainder r = 1 and repeatedly apply r = r * a % modulus, counting each step until r returns to 1. The step count at that moment is the cycle length. I cap the loop at modulus - 1 iterations because, by Fermat's argument above, the order can never exceed that - and if the loop finishes without returning to 1, no order exists and I return None (or -1 in C).
Before invoking the order computation I filter with a greatest common divisor check: if gcd(d, 10) != 1, then d shares a factor of 2 or 5 with the base, the order does not exist, and the simulation loop would never terminate by finding r == 1. Skipping these candidates is both a correctness guard and a small performance win. The Python version uses math.gcd; the C version implements the Euclidean algorithm by hand in a tight while loop.
The search window covers the top 10% of the range (with a floor of 10 iterations so tiny limits like the dev case of 10 still examine enough candidates). I justify this restriction with the cycle-length bound: a d below L/10 can produce a cycle no longer than L/10, which will always be beaten by a large d near L carrying a near-maximal cycle. The Python solution feeds a generator of (cycle_length, d) tuples into max(), relying on lexicographic tuple comparison to maximise length first and break ties toward the larger d. The C solution tracks best_len and best_d explicitly, encoding the identical tie-break in a conditional. Both take the limit as a runtime argument so the same binary handles the dev and main cases without recompilation.