Integer Partition (algorithm and recursion)

人盡茶涼 提交于 2019-11-27 19:25:36

Consider all ways of resulting n by adding some numbers less than or equal to m. As you said, we call this p(n,m). For example, p(7,3)=8 because there are 8 ways to make 7 out of numbers less than 3 as listed below: (For simplicity we can assume that always we add numbers in order from greatest to least)

  • 3+3+1
  • 3+2+2
  • 3+2+1+1
  • 3+1+1+1+1
  • 2+2+2+1
  • 2+2+1+1+1
  • 2+1+1+1+1+1
  • 1+1+1+1+1+1+1

Now we can split these combinations in two groups:

  1. Combinations whose first element is equal to m(=3 in our example:)

    • 3+3+1
    • 3+2+2
    • 3+2+1+1
    • 3+1+1+1+1
  2. Combinations whose first element is less than m:

    • 2+2+2+1
    • 2+2+1+1+1
    • 2+1+1+1+1+1
    • 1+1+1+1+1+1+1

Because every member of combinations of p(n,m) will be either in Group1 or in Group2, we can say p(n,m)=size(Group1) + size(Group2). Now if we prove that size(Group1)=p(n-m, m) and size(Group2)=p(n,m-1) by substitution we reach p(n,m)=p(n-m,m)+p(n,m-1)

Prove for size(Group1)=p(n-m, m):

By aforementioned definition p(n-m, m) is number of ways of resulting n-m by adding some numbers less than or equal to m.

  • If you append m to each combination of p(n-m, m), it will result a member of Group1. so p(n-m, m) <= size(Group1)
  • If you remove first m of each member of Group1, it will result a combination for p(n-m, m). so size(Group1) <= p(n-m, m)

=> size(Group1) = p(n-m, m). In our example:

Group1 <===correspondence===> p(4, 3) :

  • 7=3+3+1 <===========> 3+1=4
  • 7=3+2+2 <===========> 2+2=4
  • 7=3+2+1+1 <=======> 2+1+1=4
  • 7=3+1+1+1+1 <===> 1+1+1+1=4

So there is one to one correspondence between any member of p(n-m,m) and Group1 and their size is equal.

Prove for size(Group2)=p(n, m-1):

By definition, p(n,m-1) is the number of ways to result n by adding some numbers less than or equal to m-1 (less than m). If you re-read the definition of Group2, you will see that these two definitions are same as each other. => size(Group2) = p(n, m-1)

First for more than you could want to know about this function, see http://mathworld.wolfram.com/PartitionFunctionP.html.

As for this formula, remember that p(n, m) is defined to be the number of partitions of n whose largest member is at most m.

Therefore p(n, m) is the number of partitions of m whose largest member is at most m. Let us divide them according to whether the largest member actually is m.

The number of partitions whose largest member is m is the number of ways of filling in n = m + ... which is the number of partitions of n-m whose largest member is at most m which by definition is p(n-m, m).

The number of partitions of n whose largest member is at most m-1 is by definition p(n, m-1).

Therefore p(n, m) = p(n-m, m) + p(n, m-1).

        / 0 (k>n)
p(k,n)={  1 (k=n)
        \ p(k+1,n)+p(k,n-k) (k<n)

Number of partitions of n is p(1,n).

p(k,n) is number of partitions of n, allowing only addends >=k.

Like the OP's recursive formula, it adds them (as luiges90 put it) one by one (with the added inefficiency of numerous zeroes). Fortunately, though, it can be calculated inside an array with great speed:

#include <stdio.h>

/* 406 is the largest n for which p(n) fits in 64 bits */
#define MAX 406
long long int pArray[MAX][MAX];

/* Emulate array starting at 1: */
#define p(k,n) pArray[k-1][n-1]

int main(int argc, char **argv) {

 int n, k;

 for (n = 1; n < MAX; n++) {
  for (k = n; k > 0; k--) {
   if (k > n) {
    p(k, n) = 0;
   }
   else if (k == n) {
    p(k, n) = 1;
   }
   else {
    p(k, n) = p(k, n-k)+p(k+1, n);
   }
  }
 }

 for (n = 1; n < MAX; n++) {
  printf("p(%d)=%lld\n", n, p(1,n));
 }

}

Denote p(n, m) as the number of all combinations whose sum is n and each addend is less than or equals to m. The key point here is to prove the following recursive equation:

p(n, m) - p(n, m - 1) = p(n-m, m)          (1)

The left side of (1) is the difference of p(n, m) and p(n, m - 1), which are the number of all combinations that contains at least one m as addend, and leftover's sum is n-m(such that the overall is n), besides each addend is less than or equal to m. But that exactly means p(n-m, m), which is the right side of (1).

Obviously, the answer of the question should be p(n, n).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!