将K个不超过N的非负整数加起来,使它们的和为N,一共有多少种方法。

设d(i, j)表示j个不超过i的非负整数之和为i的方法数。

d(i, j) = sum{ d(k, j-1) | 0 ≤ k ≤ i },可以理解为前j-1个数之和为i-k,最后一个数为k

还有一种更快的递推办法,把这个问题转化为将N个小球放到K个盒子中的方法数,盒子可以为空。

就等价于求x + x +...+ x = N的非负整数解的个数,根据组合数学的知识容易算出结果为C(N+K-1, K-1).

所以也可以这样递推:d(i, j) = d(i-1, j) + d(i, j-1)

 #include <cstdio>

 const int M = ;
const int maxn = ;
int d[maxn + ][maxn + ]; int main()
{
for(int i = ; i <= maxn; i++)
d[][i] = ;
for(int i = ; i <= maxn; i++)
for(int j = ; j <= maxn; j++)
d[i][j] = (d[i-][j] + d[i][j-]) % M; int n, k;
while(scanf("%d%d", &n, &k) == && n && k) printf("%d\n", d[n][k]); return ;
}

代码君

05-08 08:00