题目:一共来了n(0<n<25)个同学,按照组队规则(自由组队,每队人数不限),一共会有多少种不同的组队方案呢?
递推式是:a[i][j]=a[i-1][j-1]+a[i-1][j]*j;
题解:关于本题自己一直没有思路,看了公式后也理解了好一会。
首先,将所有人按小组数量列出数组如:分成1个组,两个组........N个组,其中1个组和N个组的方案数都为1。
其次,计算其它分组的方案各有多少种。这里就是这个公式的关键了:
先将比当前少一个人并且少一个分组总数的方案直接加上(新加入的人直接新建一组,就得到人数与分组数与目标方案匹配),
再将少一人但分组数量相同的方案数乘以分组的数量(每个方案中最后的这一个人都可加到该方案的各组,使得人数匹配)。
最后,将不同分组数量的所有方案相加,得出总的方案数。
而且,a[i][0]应该是为0,不为1的。
此外还得注溢出。要用__int64类型。
http://acm.hdu.edu.cn/showproblem.php?pid=1292
#include
<
stdio.h
>
int main() {
int t, n, i, j;
__int64 a[ 26 ][ 26 ];
a[ 1 ][ 1 ] = 1 ;
a[ 1 ][ 0 ] = 0 ;
for (i = 2 ; i <= 25 ; i ++ ) {
a[i][ 0 ] = 0 ;
a[i][i] = 1 ;
for (j = 1 ; j < i; j ++ )
a[i][j] = a[i - 1 ][j - 1 ] + a[i - 1 ][j] * j;
}
scanf( " %d " , & t);
while (t -- ) {
scanf( " %d " , & n);
__int64 sum = 1 ;
for (i = 2 ; i <= n; i ++ )
sum += a[n][i];
printf( " %I64d\n " , sum);
}
return 0 ;
}
int main() {
int t, n, i, j;
__int64 a[ 26 ][ 26 ];
a[ 1 ][ 1 ] = 1 ;
a[ 1 ][ 0 ] = 0 ;
for (i = 2 ; i <= 25 ; i ++ ) {
a[i][ 0 ] = 0 ;
a[i][i] = 1 ;
for (j = 1 ; j < i; j ++ )
a[i][j] = a[i - 1 ][j - 1 ] + a[i - 1 ][j] * j;
}
scanf( " %d " , & t);
while (t -- ) {
scanf( " %d " , & n);
__int64 sum = 1 ;
for (i = 2 ; i <= n; i ++ )
sum += a[n][i];
printf( " %I64d\n " , sum);
}
return 0 ;
}
此外下面的算法也可以计算该题,但是暂时还没有想明白。
#include<stdio.h>
#include<string.h>
__int64 C(int n,int m)
{
__int64 s=1;
int i,j;
if(m>n/2)
m=n-m;
for(i=1;i<=m;i++)
{
s*=n-i+1;
s/=i;
}
return s;
}
int main()
{
int i,n,num,k,j;
__int64 F[25];
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&num);
memset(F,0,sizeof(F));
F[0]=1;
F[1]=1;
for(j=2;j<=num;j++)
{
for(k=1;k<=j;k++)
{
F[j]+=F[j-k]*C(j-1,k-1);
}
}
printf("%I64d\n",F[num]);
}
return 0;
}