微信扫一扫打赏支持

P1655 小朋友的球

P1655 小朋友的球

题目描述

@发源于 小朋友最近特别喜欢球。有一天他脑子抽了,从口袋里拿出了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。

 

洛谷题解:

 

  • 简单的动态规划,但是要加上高精度运算,不然只能得 20 分。本题和 放苹果 有些类似,但是盒子不能空着不放,也就是楼下所说的 Stirling数,应用于组合数学领域

  • 状态转移方程:f[i][j]=f[i1][j1]+f[i1][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 }

 

posted @ 2017-10-27 09:52  范仁义  阅读(847)  评论(0编辑  收藏  举报