Wolfram Mathworld :
P(n, k) は、正確に k 項の合計として n を記述する方法の数、または同等に、最大が正確に k である部分への分割の数を示します。(「正確に k」を「k 以下」に変更し、「最大は正確に k」を「k より大きい要素なし」に変更すると、分割関数 q が得られることに注意してください。) たとえば、P(5 , 3) = 2、長さ 3 の 5 のパーティションは {3, 1, 1} と {2, 2, 1} であり、最大要素 3 の 5 のパーティションは {3, 2} と {3, 1、1}。
... P(n, k) は再帰関係P(n, k) = P(n-1, k-1) + P(nk, k)
から計算できます
(Skiena 1990, p. 58; Ruskey)ここで、k > n の場合は P(n, k) = 0、P(n, n) = 1、および P(n, 0) = 0 です。
したがって、n の書き方の数を合計として計算したい場合は、次のように計算する必要があります。
P(n, k) を定義しましょう:
def p(n, k):
"""Gives the number of ways of writing n as a sum of exactly k terms or, equivalently,
the number of partitions into parts of which the largest is exactly k.
"""
if n < k:
return 0
if n == k:
return 1
if k == 0:
return 0
return p(n-1, k-1) + p(n-k, k)
n
これで、書き方の数を合計として計算できます。
n = 6
partitions_count = 0
for k in range(n + 1):
partitions_count += p(n, k)
print(partitions_count)
# Output:
# 11
再帰関数と同様p(n, k)
に、それぞれの値をディクショナリに保存することで速度を上げ(高速なハッシュベースの検索のp(n, k)
おかげで!)、計算する前に値が計算されたかどうかを確認します (値がディクショナリにあるかどうかを確認します)。 :
dic = {}
def p(n, k):
"""Gives the number of ways of writing n as a sum of exactly k terms or, equivalently,
the number of partitions into parts of which the largest is exactly k.
"""
if n < k:
return 0
if n == k:
return 1
if k == 0:
return 0
key = str(n) + ',' + str(k)
try:
temp = dic[key]
except:
temp = p(n-1, k-1) + p(n-k, k)
dic[key] = temp
finally:
return temp
フル機能:
def partitions_count(n):
"""Gives the number of ways of writing the integer n as a sum of positive integers,
where the order of addends is not considered significant.
"""
dic = {}
def p(n, k):
"""Gives the number of ways of writing n as a sum of exactly k terms or, equivalently,
the number of partitions into parts of which the largest is exactly k.
"""
if n < k:
return 0
if n == k:
return 1
if k == 0:
return 0
key = str(n) + ',' + str(k)
try:
temp = dic[key]
except:
temp = p(n-1, k-1) + p(n-k, k)
dic[key] = temp
finally:
return temp
partitions_count = 0
for k in range(n + 1):
partitions_count += p(n, k)
return partitions_count
便利なリンク: