根据题意,可知方案数为 (C(m+n,n) - C(m+n,m+1)) * m! * n!,化简为 (m+n)! * (m-n+1) / (m+1),根据大数乘法和大数除法模板即可求解。
#include <iostream>
#include <cstring>
using namespace std;
const int N = 201;
const int MAX = 3 * N;
//大数阶乘数组,fac[i][0]代表i的阶乘的位数,
//其后的fac[i][0]位为i的阶乘(逆序)
int fac[N][MAX] = { 0 };
void multiply(int a[], int b) //大数乘法模板
{
int i;
int carry = 0; //进位
for (i = 1; i <= a[0]; i++)
{
a[i] = a[i] * b + carry;
carry = a[i] / 10;
a[i] %= 10;
}
while (carry > 0)
{
a[i] = carry % 10;
carry /= 10;
++i;
}
a[0] = --i; //最终位数
}
void divide(int a[], int b) //大数除法模板
{
int res = 0; //上一位余下的数
for (int i = a[0]; i > 0; i--)
{
res = res * 10 + a[i];
a[i] = res / b;
res %= b;
}
while (a[a[0]] == 0) //更新位数
--a[0];
}
int main()
{
int m, n;
int test = 0;
fac[1][0] = 1; //1的阶乘位数为1
fac[1][1] = 1; //1的阶乘值为1
for (int i = 2; i < N; i++) //首先求出1至200的阶乘,打表
{
memcpy(fac[i], fac[i - 1], MAX * sizeof(int));
multiply(fac[i], i);
}
while (cin >> m >> n)
{
if (m == 0 && n == 0)
break;
if (m < n)
{
cout << "Test #" << ++test << ":" << endl << 0 << endl;
continue;
}
int temp[MAX] = { 0 };
memcpy(temp, fac[m + n], MAX * sizeof(int)); //(m+n)!
multiply(temp, m - n + 1); //(m+n)! * (m-n+1)
divide(temp, m + 1); //(m+n)! * (m-n+1) / (m+1)
cout << "Test #" << ++test << ":" << endl;
for (int i = temp[0]; i > 0; i--)
cout << temp[i];
cout << endl;
}
return 0;
}
继续加油。