P1655 小朋友的球
P1655 小朋友的球
题目描述
@发源于 小朋友最近特别喜欢球。有一天他脑子抽了,从口袋里拿出了N个不同的球,想把它们放到M个相同的盒子里,并且要求每个盒子中至少要有一个球,他好奇有几种放法,于是尝试编程实现,但由于他天天不好好学习,只会上B站看游泳教练,于是他向你求助。
输入输出格式
输入格式:
多组数据,每行两个数N,M。
输出格式:
每组数据一行,表示方案数。
输入输出样例
说明
【样例解释】
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。
洛谷题解:
-
简单的动态规划,但是要加上高精度运算,不然只能得 20 分。本题和 放苹果 有些类似,但是盒子不能空着不放,也就是楼下所说的 Stirling数,应用于组合数学领域
-
状态转移方程:f[i][j]=f[i−1][j−1]+f[i−1][j]×j
加一个盒子加一个球
加一个球
为什么不能加一个盒子,肯定不能加一个盒子,因为之前的是固定的
状态怎么转移
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)种方法。
注意:当m>n||m==0时直接输出0,!!!因为这个wa了好多次 也就只要加上高精就行了,先贴上c++代码:
1 #include<cmath> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 #define inf 999999999 8 #define For(i,a,b) for(i=a;i<=b;++i) 9 #define rep(i,a,b) for(i=a;i>=b;--i) 10 #define mm(a,b) memset(a,b,sizeof(a)) 11 #define ll long long 12 using namespace std; 13 ll read(){ 14 ll sum=0,flag=1; 15 char c=getchar(); 16 while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();} 17 while(c>='0'&&c<='9')sum=sum*10+c-'0',c=getchar(); 18 return sum*flag; 19 } 20 ll maxx(ll x,ll y){ 21 if(x<y)return y; 22 return x; 23 } 24 ll minn(ll x,ll y){ 25 if(x<y)return x; 26 return y; 27 } 28 ll abss(ll x){ 29 if(x>=0)return x; 30 return -x; 31 } 32 struct node{ 33 ll a[500],len; 34 node(){mm(a,0);len=0;}//记得初始化 35 }; 36 node t[111][111]; 37 node operator + (node c,node d){ 38 node h;h.len=maxx(c.len,d.len); 39 int i; 40 for(i=1;i<=h.len;i++){ 41 h.a[i]+=c.a[i]+d.a[i]; 42 if(h.a[i]>=10){ 43 h.a[i+1]+=h.a[i]/10; 44 h.a[i]%=10; 45 if(i==h.len)h.len++; 46 } 47 } 48 return h; 49 } 50 node operator * (node c,ll u){ 51 node h;h.len=c.len; 52 int i; 53 for(i=1;i<=h.len;i++){ 54 h.a[i]+=c.a[i]*u; 55 if(h.a[i]>=10){ 56 h.a[i+1]+=h.a[i]/10; 57 h.a[i]%=10; 58 if(i==h.len)h.len++; 59 } 60 } 61 return h; 62 } 63 int main(){ 64 ll i,j,m,n; 65 For(i,1,100)t[i][0].a[1]=0,t[i][i].a[1]=t[i][1].a[1]=1,t[i][0].len=t[i][i].len=t[i][1].len=1; 66 For(i,2,100){ 67 For(j,2,i-1){ 68 t[i][j]=t[i-1][j-1]+t[i-1][j]*j; 69 } 70 } 71 while(scanf("%lld%lld",&m,&n)!=EOF){ 72 if(n==0||n>m){printf("0\n");continue;} 73 rep(i,t[m][n].len,1)printf("%lld",t[m][n].a[i]); 74 printf("\n"); 75 } 76 return 0; 77 }