ネタ元
http://www.kmonos.net/wlog/113.html#_2256100904
階乗を求めるのに、
k! = limn → ∞ nk / nCk
という方法がある。これはどこかで見たことがあるような気がする。ただ、n = (k + 1)k + 2とすれば必ず整数の割り算で正しい答えは出る、というのは見たことがなかった。
この証明は簡単で、
nk / nCk = k! / 1...(1 - (k - 1) / n)
ここに n = (k + 1)k + 2 を代入すると、
k! / 1...(1 - (k - 1) / (k + 1)k + 2) < k! / 1...(1 - 1 / (k + 1)k + 1) < k! / (1 - 1 / (k + 1)k + 1)k < k! / (1 - k / (k + 1)k + 1) < k! / (1 - 1 / (k + 1)k) < k! / (1 - 1 / k!)
だから、正しい答えになります(見にくいですね)。
ただ、この評価はかなーり雑ですよね。もっと小さな n でもだいじょうぶそうですよね。元記事の趣旨とはかけ離れますが、nをどう取るのがよいかをここでは探りたいと思います。
まずは、n の下限をプログラムで求めることを考えましょう。2分探索します。
def C(n, k): return 1 if k == 0 else C(n, k - 1) * (n - k + 1) / k def factorial(k): return 1 if k == 0 else k * factorial(k - 1) def factorial2(k, n): return n ** k / C(n, k) def lower_n(k): f = factorial(k) def lower_n_(min_n, max_n): if min_n == max_n: return min_n n = min_n * 2 if max_n == -1 else (min_n + max_n) / 2 if n == min_n: return max_n f2 = factorial2(k, n) if f2 == f: return lower_n_(min_n, n) else: return lower_n_(n, max_n) return lower_n_(k, -1) N = 10 for k in range(1, N + 1): rough_n = (k + 1) ** (k + 2) exact_n = lower_n(k) print k, rough_n, exact_n
この結果は、
1 8 2 2 81 4 3 1024 21 4 15625 149 5 279936 1207 6 5764801 10810 7 134217728 105853 8 3486784401 1128977 9 100000000000 13063701 10 3138428376721 163296026
右側が n の下限です。
さて、問題は n をどう評価するかです。ちょっと考えてみたんですが、意外と難しいです。ラフに計算してみたら、k! k2 となりました。
1 2 1 2 4 8 3 21 54 4 149 384 5 1207 3000 6 10810 25920 7 105853 246960 8 1128977 2580480 9 13063701 29393280 10 163296026 362880000
右側がそのラフなnです。
また今度、ちゃんと考えてみます。