https://www.luogu.org/problem/show?pid=1655
题目描述
@发源于 小朋友最近特别喜欢球。有一天他脑子抽了,从口袋里拿出了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)种方法。
注意:当m>n||m==0时直接输出0,!
*/
不用高精20分。
1 #include <algorithm> 2 #include <cstring> 3 #include <cstdio> 4 5 using namespace std; 6 7 int n,m,f[110][110]; 8 9 int main() 10 { 11 for(int i=0;i<=100;i++) f[i][i]=1; 12 for(int i=1;i<=100;i++) 13 for(int j=1;j<=i;j++) 14 f[i][j]=f[i-1][j-1]+f[i-1][j]*j; 15 for(;~scanf("%d%d",&n,&m);) 16 { 17 if(!m||m>n) puts("0"); 18 else printf("%d ",f[n][m]); 19 } 20 return 0; 21 }
初值 f[1][1]=1 从2开始枚举
高精AC
1 #include <algorithm> 2 #include <cstring> 3 #include <cstdio> 4 5 using namespace std; 6 7 int n,m; 8 struct Gj 9 { 10 int num[555]; 11 Gj() { for(int i=1;i<=500;i++) num[i]=0;num[0]=1; } 12 void print() { for(int i=num[0];i;i--) printf("%d",num[i]); } 13 }f[110][110]; 14 Gj mul(Gj a,int x) 15 { 16 for(int ove=0,i=1;i<=a.num[0];i++) 17 { 18 a.num[i]=a.num[i]*x+ove; 19 if(a.num[i]>9) 20 { 21 ove=a.num[i]/10; 22 a.num[i]%=10; 23 a.num[0]=max(a.num[0],i+1); 24 } 25 else ove=0; 26 } 27 for(;!a.num[a.num[0]]&&a.num[0];) a.num[0]--; 28 return a; 29 } 30 Gj add(Gj a,Gj b) 31 { 32 Gj c; 33 c.num[0]=max(a.num[0],b.num[0]); 34 for(int i=1,x=0;i<=c.num[0];i++) 35 { 36 c.num[i]=a.num[i]+b.num[i]+x; 37 if(c.num[i]>9) 38 { 39 x=c.num[i]/10; 40 c.num[i]%=10; 41 c.num[0]=max(i+1,c.num[0]); 42 } 43 else x=0; 44 } 45 for(;!c.num[c.num[0]]&&c.num[0];) c.num[0]--; 46 return c; 47 } 48 49 int main() 50 { 51 // for(int i=0;i<=100;i++) f[i][i].num[1]=1; 52 f[1][1].num[1]=1; 53 for(int i=2;i<=100;i++) 54 for(int j=1;j<=i;j++) 55 { 56 Gj tmp=mul(f[i-1][j],j); 57 f[i][j]=add(tmp,f[i-1][j-1]); 58 } 59 for(;~scanf("%d%d",&n,&m);) 60 f[n][m].print(),printf(" "); 61 return 0; 62 }