首页 > 代码库 > 小朋友的球

小朋友的球

题目描述

@发源于 小朋友最近特别喜欢球。有一天他脑子抽了,从口袋里拿出了N个不同的球,想把它们放到M个相同的盒子里,并且要求每个盒子中至少要有一个球,他好奇有几种放法,于是尝试编程实现,但由于他天天不好好学习,只会上B站看游泳教练,于是他向你求助。

输入输出格式

输入格式:

 

多组数据,每行两个数N,M。

输出格式:

每组数据一行,表示方案数。

输入输出样例

输入样例#1:
4 2
1 1
输出样例#1:
7
1

说明

【样例解释】

N=4,M=2

1,2 3 4

2,1 3 4

3,1 2 4

4,1 2 3

1 2,3 4

1 3,2 4

1 4,2 3

对于20%的数据,满足1≤N,M≤10;

对于100%的数据,满足1≤N,M≤100,数据组数≤10。

stirling数,递推公式s[i][j]=s[i-1][j]*j+s[i-1][j-1]

 

S(p,k)的一个组合学解释是:将p个物体划分成k个非空的不可辨别的(可以理解为盒子没有编号)集合的方法数。

 

k!S(p,k)是把p个人分进k间有差别(如:被标有房号)的房间(无空房)的方法数。

 

S(p,k)的递推公式是:S(p,k)=k*S(p-1,k)+S(p-1,k-1) ,1<= k<=p-1

 

边界条件:S(p,p)=1 ,p>=0 S(p,0)=0 ,p>=1

 

递推关系的说明:

 

考虑第p个物品,p可以单独构成一个非空集合,此时前p-1个物品构成k-1个非空的不可辨别的集合,方法数为S(p-1,k-1);

 

也可以前p-1种物品构成k个非空的不可辨别的集合,第p个物品放入任意一个中,这样有k*S(p-1,k)种方法。

高精度使用重载运算符会很方便

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 struct node{
 7     long long a[500],len;
 8     node()
 9     {memset(a,0,sizeof(a));len=0;}
10 };
11 node f[101][101];
12 node operator + (node c,node d)
13 {
14     node h;
15     h.len=max(c.len,d.len);
16     int i;
17     for(i=1;i<=h.len;i++){
18         h.a[i]+=c.a[i]+d.a[i];
19         if(h.a[i]>=10){
20             h.a[i+1]+=h.a[i]/10;
21             h.a[i]%=10;
22             if(i==h.len)h.len++;
23         }
24     }
25     return h;
26 }
27 node operator * (node c,long long u)
28 {
29     node h;
30     h.len=c.len;
31     int i;
32     for(i=1;i<=h.len;i++){
33         h.a[i]+=c.a[i]*u;
34         if(h.a[i]>=10){
35             h.a[i+1]+=h.a[i]/10;
36             h.a[i]%=10;
37             if(i==h.len)h.len++;
38         }
39     }
40     return h;
41 }
42 int main()
43 {int n,m,i,j;
44     while (cin>>n>>m)
45     {
46         if (n<m)
47         {
48             printf("0\n");
49         }
50         else if (n==m)
51         {
52             printf("1\n");
53         }
54         else 
55         {
56             for (i=0;i<=n;i++)
57             f[i][i].a[1]=1,f[i][1].a[1]=1,f[i][i].len=f[i][1].len=1;
58             for (i=2;i<=n;i++)
59             {
60                 for (j=2;j<=i-1;j++)
61                  f[i][j]=f[i-1][j]*j+f[i-1][j-1];
62             }
63 
64       for (i=f[n][m].len;i>=1;i--)
65       printf("%lld",f[n][m].a[i]);
66       printf("\n");
67         }
68         
69     }
70 }

 

小朋友的球