原题链接:HDU's ACM 1133 Buy The Tickets
分析:这题类似括号的配对问题,可以参考卡特兰数。当m<n时,S(m,n)=0;否则,S(m,n) = (m+n)!*(m-n+1)/(m+1)。利用大数乘法、除法解决之;可以通过存储已经计算的结果,来提升性能。
AC Code:
#include <stdio.h>
#include <string.h>
#define MAXN 150
#define POS_OF_LEN MAXN-1
#define UNDEFINE -1
#define MAX_PER_NUM 10000000
#define TOTAL_NUM 201
int factorial[TOTAL_NUM][MAXN];
int main()
{
int m, n;
int i, j;
int len;
int testNum=0;
int res[MAXN];
int div, mul;
int temp;
// 计算阶乘
factorial[0][0] = 1;
factorial[0][POS_OF_LEN] = len = 1;
for(i=1;i<TOTAL_NUM;++i) {
for(j=0;j<len;++j)
factorial[i][j] = factorial[i-1][j] * i;
for(j=0;j<len;++j){
factorial[i][j+1] += factorial[i][j] / MAX_PER_NUM;
factorial[i][j] %= MAX_PER_NUM;
}
len = factorial[i][len]? len+1:len;
factorial[i][POS_OF_LEN] = len;
}
while(scanf("%d%d", &m, &n) == 2){
if(!m && !n)
break;
printf("Test #%d:\n", ++testNum);
if(m<n){
printf("0\n");
} else {
memset(res, 0, sizeof(int)*MAXN);
len = factorial[m+n][POS_OF_LEN];
for(i=0;i<len;++i)
res[i] = factorial[m+n][i];
// 大数乘以小数
mul = m-n+1;
for(i=0;i<len;++i)
res[i] *= mul;
for(i=0;i<len;++i){
res[i+1] += res[i] / MAX_PER_NUM;
res[i] %= MAX_PER_NUM;
}
len = res[len]? len+1:len;
// 大数除以小数
div = m+1;
temp = 0;
for(i=len-1;i>=0;--i){
temp = temp*MAX_PER_NUM + res[i];
res[i] = temp / div;
temp %= div;
}
len = res[len-1]? len:len-1;
printf("%d", res[--len]);
while(len>0)
printf("%07d", res[--len]);
printf("\n");
}
}
return 0;
}