views:

407

answers:

3

Today I encountered this article about decimal expansion and I was instantaneously inspired to rework my solution on Project Euler Problem 26 to include this new knowledge of math for a more effecient solution (no brute forcing). In short the problem is to find the value of d ranging 1-1000 that would maximize the length of the repeating cycle in the expression "1/d".

Without making any further assumptions about the problem that could further improve the effecienty of solving the problem I decided to stick with

10^s=10^(s+t) (mod n)

which allows me for any value of D to find the longest repeating cycle (t) and the starting point for the cycle (s).

The problem is that eksponential part of the equation, since this will generate extremely large values before they're reduced by using modulus. No integral value can handle this large values, and the floating point data types seemes to be calculating wrong.

I'm using this code currently:

Private Function solveDiscreteLogarithm(ByVal D As Integer) As Integer
Dim NumberToIndex As New Dictionary(Of Long, Long)()
Dim maxCheck As Integer = 1000

For index As Integer = 1 To maxCheck
   If (Not NumberToIndex.ContainsKey((10 ^ index) Mod D)) Then
        NumberToIndex.Add((10 ^ index) Mod D, index)
   Else
        Return index - NumberToIndex((10 ^ index) Mod D)
   End If
Next

Return -1
End Function

which at some point will compute "(10^47) mod 983" resulting in 783 which is not the correct result. The correct result should have been 732. I'm assuming it's because I'm using integral data types and it's causing overflow. I tried using double instead, but that gave even stranger results.

So what are my options?

+4  A: 

Instead of using ^ to do your powers, I would do a for loop using multiplication and then taking the mod of the number as you go along by using a conditional to check if the number calculated is greater than the mod. This helps to keep the numbers smaller and within range of your mod number.

AlbertoPL
I wasn't quite sure about it, but that means that the following definition holds true? x*y mod 7 = (x mod 7 ) * (y mod 7)
Qua
That is correct.
AlbertoPL
Qua --- (x * y) mod 7 = ((x mod 7) * (y mod 7)) mod 7
Dave Hinton
Alright, just tested it, and it worked flawlessly. Thanks a bunch. Can't believe I missed that definition. I even browsed trying to find it. Guess I should have just tried to deduce it myself.
Qua
+1  A: 

I'll give you a hint from my own solution to this.

With each decimal expansion of the fraction, you end up with a remainder, which if multiplied by the current decimal place, is an integer. Since this remainder is all you need to determine the next decimal expansion, you can use it to make predictions about the subsequent expansion.

TokenMacGuy
I'm not quite sure I follow you. I don't actually do any decimal expansions directly.
Qua
A: 

See my post for this other question, getting the nth digit of a fraction, you may find some useful leads on what to try. (Methinks the answer is the largest prime less than 1000.) (Correction: the largest prime or Carmichael number less than 1000.)

Jason S