题意:
N只不同的小猪分配到M所相同的房子,问有多少种方法(每所房子至少要有一只小猪)
思路:
对于F[n][m],考虑,第n只小猪单独考虑,有两种情况:
1)前n-1只小猪在m-1所房子里面,第n只小猪单独一个房子
2)前n-1只小猪在m所房子里面,第n只小猪在任意一个房子里面
于是F[n][m] = F[n-1][m-1] + m*F[n-1][m]
初始条件F[k][1] = 1:k只小猪放在一个房子里面有1种方法。
注意:
数据比较大,会超出long long,所以用高精度。
代码:
#include <cstdio>
#include <cstring>
#define N 51
const int MAXLEN = 50;
class BigInt
{
public:
int data[MAXLEN];
BigInt()
{
memset(data, 0, sizeof(data));
data[0] = 1;
}
BigInt operator = (const BigInt &ob)
{
memcpy(data, ob.data, sizeof(data));
return *this;
}
BigInt operator + (const BigInt &ot)
{
BigInt sum;
int i;
sum.data[0] = data[0]>ot.data[0] ? data[0] : ot.data[0];
for (i = 1; i <= sum.data[0]; ++ i)
{
sum.data[i] += data[i] + ot.data[i];
sum.data[i+1] += sum.data[i] / 10;
sum.data[i] %= 10;
}
while (sum.data[i] != 0)
{
sum.data[i+1] += sum.data[i] / 10;
sum.data[i] %= 10;
i ++;
}
sum.data[0] = i - 1;
while(sum.data[sum.data[0]] == 0 && sum.data[0] > 1)
sum.data[0] -= 1;
return sum;
}
BigInt operator * (const int n)
{
BigInt product;
int i;
for (i = 1; i <= data[0]; ++ i)
{
product.data[i] += data[i] * n;
product.data[i+1] += product.data[i] / 10;
product.data[i] %= 10;
}
while (product.data[i] != 0)
{
product.data[i+1] += product.data[i] / 10;
product.data[i] %= 10;
i ++;
}
product.data[0] = i-1;
while(product.data[product.data[0]] == 0 && product.data[0] > 1)
product.data[0] -= 1;
return product;
}
void print()
{
for (int i = data[0]; i >= 1; -- i)
printf("%d", data[i]);
}
};
BigInt f[N][N];
void calc()
{
for (int i = 1; i < N; ++ i)
f[i][1].data[1] = 1;
for (int i = 2; i < N; ++ i)
for (int j = 1; j < N; ++ j)
f[i][j] = f[i-1][j-1] + f[i-1][j]*j;
}
int t, n, m;
int main()
{
calc();
scanf("%d", &t);
while (t --)
{
scanf("%d %d", &n, &m);
f[n][m].print();
printf("\n");
}
}