求组合数使用公式(n+1)Cm=nCm+nC(m-1)。
#include <stdio.h>
enum {
SUCCESS = 0,
FAILURE = 1,
ZERO = 0,
ONE,
TWO,
THREE = 3,
MAX_M = 100,
MAX_N = 1000,
MAX_K = 20,
MODVALUE = 5201314
};
int g_comDp[MAX_N + MAX_M + ONE][MAX_M + 1] = {0};
int g_equalN = 0;
int g_equalM = 0;
int InitCom()
{
int m, n, k;
int res = scanf_s("%d%d%d", &m, &n, &k);
if (res < THREE || m > MAX_M || n > MAX_N || k > MAX_K || m < ZERO || n < ZERO || n < ZERO) {
printf("[error]%s.\n", __FUNCTION__);
return -1;
}
int equalBall = n - m * k;
int equalBox = m;
if (equalBall < ZERO) {
return FAILURE;
} else {
g_equalN = equalBall + equalBox - ONE; // 等效求组合(n+m-1)C(m-1)
g_equalM = m - ONE;
return SUCCESS;
}
}
void InitComDp()
{
for (int i = ONE; i <= g_equalN; ++i) {
g_comDp[i][i] = ONE;
g_comDp[i][ONE] = i;
}
}
void LookupRes()
{
for (int i = TWO; i < g_equalN; ++i) {
for (int j = TWO; j <= g_equalM; ++j) {
if (j >= i + 1) {
break;
}
g_comDp[i + 1][j] = (g_comDp[i][j] + g_comDp[i][j - 1]) % MODVALUE;
}
}
}
int main()
{
int res = InitCom();
if (res != SUCCESS) {
printf("%d", ZERO);
return res;
}
if (g_equalM == g_equalN) {
printf("%d", ONE);
return 0;
}
InitComDp();
LookupRes();
printf("%d", g_comDp[g_equalN][g_equalM]);
return 0;
}