Project Euler 73: Counting fractions in a range

For fractional \ (n-/ D \) , where \ (n, d \) are positive integers, if \ (n <d \) and the greatest common divisor of both the \ (HCF (n, d) = 1 \) , this score it is called a simple fraction. If we \ (d \ le8 \) all simple fraction in ascending order, there are:
\ [\ FRAC {. 1} {. 8}, \ FRAC {. 1} {. 7}, \ FRAC {. 1} {6}, \ frac {1 } {5}, \ frac {1} {4}, \ frac {2} {7}, \ frac {1} {3}, \ frac {3} {8}, \ frac {2} {5}, \ frac {3} {7}, \ frac {1} {2}, \ frac {4} {7}, \ frac {3} {5}, \ frac {5} { 8}, \ frac {2} {3}, \ frac {5} {7}, \ frac {3} {4}, \ frac {4} {5}, \ frac {5} {6}, \ frac {6} {7}, \
frac {7} {8}, \] see \ (1/3 \) and \ (1/2 \) has between three points. When \ (d \ le12000 \) when the number of points in this set of simple fractions in ascending order of \ (1/3 \) and \ (1/2 \) between?

Analysis: There are at least two solutions to this problem: The first solution is to use the mentioned between Farey Sequence nature, relatively easy to understand, but the efficiency is not high enough; The second solution is to use the law of seven similar Q12 derivation method, this problem into a dynamic programming problem, this method is very efficient, but also more difficult to understand. The following two methods are outlined:

Method a : listed title Farey Sequence satisfy the following two properties:

  • Two-fraction \ (a / b \) and \ (c / d \) in Farey Sequence necessary and sufficient conditions are adjacent \ (bc-ad = 1 \ )
  • Farey Sequence of three consecutive scores \ (a / b, c / d, e / f \) satisfies the condition \ (c / d = (a + e) / (b + f) \)

Questions asked in \ (d \ le12000 \) when, Farey Sequence in in \ (1/3 \) and \ (1/2 \) score between how many? Then we can think as follows: The first step, first determine \ (d \ le12000 \) under conditions most close to \ (1/3 \) score is how much? The nature of a listed above, assuming that the score is \ (P / Q \) , then \ (= 3P-Q. 1 \ Rightarrow3p. 1 = Q + \) , i.e. \ (q + 1 \) should be a multiple of three , the \ (Q \) maximum can only take \ (11999 \) , whereby to obtain \ (P = 12000/4000 =. 3 \) , i.e. \ (d \ le12000 \) , the most closely adjacent \ (1/3 \ ) score should be \ (4000/11999 \) . The second step, known \ (1/3 \) and (4000/11999 \) \ the case immediately, we have to calculate the next close \ (4000/11999 \) scores, and so continue to go on record have been calculated the number of scores generated, until a next fraction becomes\ (1/2 \) is stopped, the number of points recorded this time is the subject of the request. The two properties listed above, because \ (c / d \) is the simplest form of scores, there \ (KD = B + F \ F = Rightarrow KD-B \) , according to the meaning of problems have \ (kd- B \ le12000 \) , when this condition is met \ (K \) maximum value of \ (\ lfloor (12000 + B) / D \ rfloor \) , then immediately \ (a / b \) and \ (c / D \) next fraction \ (e / f \) satisfy the condition:
\ [E = \ lfloor (12000 + B) / D \ rfloor \ CDOT CA, F = \ lfloor (12000 + B) / D \ rfloor \ cdot bb \]
so we can follow the order from small to large listed Farey sequence in \ (1/3 \) all score after until the score reached \ (1/2 \) cut-off, that \ ( f = 2 \) is turned off, then the score is the number of return subject desires. This method of time complexity of about \ (O (the n-^ 2) \) , it can still cope with in dealing with small-scale problems, but when dealing with large-scale problems will be time-consuming for a long time. The second method described below:

Method two: First, two functions are defined as follows:
\ [\ the aligned the begin {} F. (N) = & Card \ Bigg \ {\ {n-FRAC} {K}: \ FRAC. 1 {{}}. 3 <\ {K FRAC } {n} <\ frac { 1} {2}, n \ le N \ bigg \} \\ R (N) & = card \ bigg \ {\ frac {k} {n}: \ frac {1} { 3} <\ frac {k}
{n} <\ frac {1} {2}, n \ le N, gcd (k, n) = 1 \ bigg \} \ end {aligned} \] where \ (Card \ ) represents the cardinality of the set, i.e. the number of elements in the set, then we can see clearly \ (R (N) \) is the value of our requirements. The seven Q12 while similar idea, we have:
\ [F. (N) = \ sum_ {m} ^ = NR. 1 (\ lfloor \ FRAC {N} {m} \ rfloor) \ Rightarrow F. (N ) = R (N) + \
sum_ {m = 2} ^ NR (\ lfloor \ frac {N} {m} \ rfloor) \] there is:
\ [R & lt (N) = F. (N) - \ sum_ { m = 2} ^ NR (\
lfloor \ frac {N} {m} \ rfloor) \] obviously we get a seven Q12 recursive very similar, can be solved using dynamic programming, and can be used for divisible skill block. The problem now is that we need to determine \ (F (N) \) , only when \ (F (N) \) when easily calculated, above recursive derivation is meaningful. If we let \ (N = R & lt 6Q +, 0 \ R & lt Le <. 6 \) , then:
\ [F \ left (N \ right) = \ sum_ {i = 1} ^ N {\ left (\ bigg \ lfloor \ frac {i-1} {2} \ bigg \ rfloor - \ bigg \ lfloor \ frac { i} {3} \ bigg \ rfloor \ right) = q \ left (3q-2 + r \ right) + \ begin {cases} 1 & r = 5 \\ 0 & r \ ne 5 \\\ end {cases}} \]
the formula we can easily calculate the \ (F. (N) \) . The method of time complexity is about two \ (O (n-^ {3/4}) \) , sublinear algorithm is, when dealing with a large-scale data with respect to the method has a great advantage.

The coding is as follows:

# approach 1, time cost = 2.97 s ± 6.42 ms

def farey_seq(n=12000):
    b, d = 3, 11999
    ans = 0
    while d!=2:
        ans += 1
        k = int((n + b) / d)
        b, d = d, k * d - b
    return ans


# approach 2, time cost = 101 ns ± 0.171 ns

from functools import lru_cache

def number_theory_block(f,n,i=1):
    ans = 0
    while i <= n:
        j = n//(n//i)
        ans += (j-i+1)*f(n//i)
        i = j + 1
    return ans

def fractions_count(n):
    q,r = divmod(n,6)
    i = 1 if r == 5 else 0
    ans = q*(3*q-2+r)+i
    return ans

@lru_cache(maxsize=2048)
def reduced_fractions_count(n=12000):
    if n == 1:
        return 0
    else:
        return fractions_count(n) - number_theory_block(reduced_fractions_count,n,2)

Guess you like

Origin www.cnblogs.com/metaquant/p/12015942.html