プロジェクトオイラー73:範囲内のカウントの分画

分別のための(N / D \)\、ここで\(N、D \)正の整数、場合である(N <D \)\との両方の最大公約数\(HCF(N、D) = 1 \) 、これは簡単な分数と呼ばれる得点します。もし我々\(D \ LE8 \)昇順ですべての単純端数がある
{8} {7} \ [\ FRAC {1}、\ FRAC {1}、\ 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}、\] 参照\(1/3 \)\(1/2 \)の三点との間に有しています。場合\(D \ le12000 \)ときの昇順に単純な画分のこのセットのポイント数\(1/3 \)\(1/2 \)の間?

分析:この問題には少なくとも二つの解決策があります:最初のソリューションは、間を言及使用することですファレイシーケンス比較的容易に理解するために、自然が、効率が高いだけでは不十分であり、第二の溶液を7と同様のQ12の法則を使用することです導出方法は、動的なプログラミングの問題にこの問題は、この方法は、非常に効率的ですが、また理解することはより困難。次の2つの方法が概説されています。

方法:記載されているタイトルファレイのシーケンスを満たす次の2つのプロパティ:

  • 二画分(\ / B \)\(C / D \)ファレイ配列の必要十分条件は隣接している\(BC-AD = 1 \ )
  • ファレイ配列三つの連続スコアの\(/ B、C / D、E / F \) を満たす条件\(C / D =( +電子)/(B + F)\)

質問はで尋ねた(D \ le12000 \)\、ときファレイシーケンスにして(1/3 \)\\(1/2 \)どのように多くの間のスコア?その後、我々は次のように考えることができます:最初の決定最初のステップ、(D \ le12000 \)\最も近い条件で\(1/3 \)スコアはどのくらいですか?上記の性質、スコアであると仮定すると(P / Q \)\次に、\(3P-Q = 1 \ Rightarrow3p。1 = Q + \) すなわち\(Q + 1 \)は、 3の倍数でなければなりません、\(Q \)最大値のみ取ることができる(\ 11999)を\、それによって得ることが\(P = 4000分の12000 = 3 \) すなわち\(D \ le12000 \) 最も近接1/3(\ \ )のスコアでなければなりません\(11999分の4000 \) 第二段階、知られている\(1/3 \)(11999分の4000 \)\場合はすぐに、私たちは次のクローズを計算する必要が\(11999分の4000 \)スコア、及びその記録に行くし続けるが計算されています次のフラクションになるまで、生成されたスコアの数\(1/2 \)停止し、この時間を記録したポイント数は、要求の対象です。上記の2つのプロパティ、ため(C / D \)\スコアの最も単純な形式で、そこ\(KD = B + F \ F = RIGHTARROW KD-Bは\) 問題の意味に応じて有している\(kd-をB \ le12000 \)この条件が満たされる、\(K \)の最大値(\ \ lfloor(12000 + B)/ D \ rfloor \) 直ちに\(/ B \)\(C / D \)次分数\(E / F \)の条件を満足する:
\ [E = \ lfloor(12000 + B)/ D \ rfloor \ CDOT CA、F = \ lfloor(12000 + B)/ D \ rfloor \ CDOT BB \]
我々は大記載されているに小さなものから順に従うことができますので、ファレイ数列\(1/3 \)のスコアに到達するまで、結局スコア(\ 1/2)\、カットオフその\( F = 2 \)は、次にスコアが戻り被写体が所望の数であり、オフにされます。程度の時間複雑さのこの方法\(O(N ^ 2)\) それはまだ小規模な問題に対処する上で対処することができますが、大規模な問題を扱うときには時間がかかり、長い時間のためになります。第二の方法は、以下に記載します:

方法2:次のようにまず、二つの機能が定義されています:
\ [\開始整列{} F(N)=&カード\ Biggの\ {\ {N-FRAC} {K}:\ FRAC 1 {{}} 3 <\ {K FRAC } {N} <\ FRAC { 1} {2}、N \ルN \ Biggの\} \\ R(N)=&カード\ Biggの\ {\ FRAC {K} {N}:\ FRAC {1} { 3} <\ FRAC {K} {N} <\ FRAC {1} {2}、N \ルN、GCD(K、N)= 1 \ Biggの\} \端{整列} \] \(カード\ )セット内の要素の数、すなわち、集合の基数を表し、我々ははっきり見ることができる)(R(N)\ \我々の要件の値です。:同様の考え、我々はしばらく7 Q12 \ [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)\] がある:\ [R&LT(N)= F(N) - \ sum_ { M = 2} ^ NR(\ lfloor \ FRAC {N} {M} \ rfloor)\] 明らかに、我々は非常によく似た7 Q12の再帰を取得し、動的計画法を用いて解くことができ、そしてために使用することができます割り切れるスキルブロック。問題は、今我々が決定する必要があることである(F(N)\)\場合にのみ、\(F(N)\)を容易に算出するとき、再帰的な派生上に有意義です。私たちが許可すれば(N = R&LT 6Q +、0 \ R&LTル<6 \)\:、その後、





\ [F \は(N \左右)= \ sum_ {I = 1} ^ N {\ \ Biggの\ lfloor \ FRAC {I-1} {2} \ Biggの\ rfloor(左- {\ Biggの\ lfloor \ FRAC I} {3} \ Biggの\ rfloor \右)= Q \(3Q-2 + R \右)左+ \開始{ケース} 1&R = 5 \\ 0&R \ NE 5 \\\端{ケース}} \]
式は、我々は簡単に計算することができる\(F(N)を\) 時間計算の方法は、約2である\(O(N ^ {3/4})\) サブリニアアルゴリズムは、メソッドに対して大規模なデータを扱う場合は大きな利点を有しています。

次のようにコーディングは次のとおりです。

# 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)

おすすめ

転載: www.cnblogs.com/metaquant/p/12015942.html