我已经定义了一个递归函数,它接受一个数字n
,并返回list
个与该数字相加的数字列表(分区):
def P(n):
# base case of recursion: zero is the sum of the empty list
if n == 0:
yield []
return
for p in P(n-1):
p.append(1)
yield p
p.pop()
if p and (len(p) < 2 or p[-2] > p[-1]):
p[-1] += 1
yield p
我想知道如何让函数返回数字n
的分区的 number 。
例如,P(6)
会返回10
。
答案 0 :(得分:4)
如果查看Wikipedia上Partiton (number theory)页面的“分区函数公式”部分,您会发现没有简单方法来查找分区号。
相反,你最好的选择可能是:
sum(1 for _ in P(6))
或者,稍微简单但是大量的内存占用
len(list(P(6)))
使用您现有的功能。
另请注意,如果您希望能够保存P
返回的值,则应yield
p[:]
而不是p
- 您想要复制,不会反复产生相同的列表(您更改)。你可以看到为什么list(P(6))
- 它会返回一遍又一遍地重复的同一个空列表的列表。
有关分区的更多信息,请参阅Partitioning with Python。
答案 1 :(得分:0)
P(n,k)表示以正好为k的总和形式写入n 术语,或等效地,划分成部分的数量 最大恰好是k。 (请注意,如果“正好是k”更改为“ k 或更少”和“最大就是k”,更改为“无元素” 大于k”,则获得分区函数q。) 例如,P(5,3)= 2,因为长度为3的5的分区为{3,1,1} 和{2,2,1},元素5为3的5的分区为{3,2} 和{3,1,1}。
...
P(n,k)可以从递归关系中计算出来 P(n,k)= P(n-1,k-1)+ P(n-k,k) (Skiena 1990,第58页; Ruskey),其中k> n,P(n,n)= 1且 P(n,k)= 0 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)
的值保存在字典中(感谢the fast hash-based search!)来提高速度,并检查是否已计算出该值(在计算之前,请检查该值是否在字典中)
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
有用的链接:
答案 2 :(得分:-2)
以下是Java中用于计算所需结果的示例。
/**
* Returns the number of ways the number n can be partitioned
* into sums of positive integers larger than k.
* @param k
* @param n
* @return
*/
public static long partition(long k, long n){
long sum = 0;
if(k > n) return 0;
if(k == n) return 1;
sum += partition(k+1, n) + partition(k, n-k);
return sum;
}