小球装箱问题八连(组合数学)

n个球不可区分,m个盒子不可区分:

盒子不可为空:dp[n][m]= dp[n-m][m]+ dp[n-1][m-1]

盒子可为空:dp[n+m][m]= dp[n][m]+ dp[n+m-1][m-1]

对于盒子不可以为空的时候:

int dp[100][100]={0};
dp[1][1]=1;
for(int i=2;i<=n;i++){
    for(int j=1;j<=n;j++){
        dp[i][j]=dp[i-j][j]+dp[i-1][j-1];
    }      
}

这里解释一下这个递推式,dp[i][j]的方案数中分两类一类是方案中包含1的,一类是不包含1的:

  1.包含1的由于一定分解1,所以这一类的答案等价于求dp[i-1][j-1];

  2.由于一定不分解出1,所以我们反向思考如果在dp[i-m][[j]的所有方案数上全部加上1,这样所有方案数不就存在1了吗?而且和还是i。

对于盒子可以为空的时候:

  我们假设可以现在每个盒子里面放一个球,也就是总球数是n+m个球,放进m个盒子里面,然后我在从每个盒子里面拿走一个小球,不就是盒子可以为空的情况了吗?所以我们可以把这个问题转化为求上面式子中的dp[n+m][m]=dp[n][m]+dp[n+m-1][m-1];

 

n个球不可区分,m个盒子可区分:

方法:隔板法

盒子不可为空:C(n-1,m-1)
盒子可为空:C(n+m-1,m-1)

盒子不可以为空:

由于球是不可区分,盒子是可以区分,我们可以采用上述的隔板法(在高中应该学过了),n个小球有n-1个间隙,现在分成m个集合,需要插入m-1个隔板,不就是C(n-1,m-1)吗?

盒子可以为空:

  同样的套路我们可以先在每个盒子里面放一个小球,需要m个,然后把问题转化为上面不可为空的情况。

 

n个球可区分,m个盒子不可区分:

方法:第二类斯特林数
盒子不可为空:第二类斯特林数 S[n][m]
盒子可为空:第二类斯特灵数求和 ΣS[n][m](假设一个为空,两个为空,三个为空……说白了不就是求和吗?)

第二类斯特林数的定义:表示将n个不同的元素拆分成m个集合的方案数

求第二类斯特林数的代码:

1 for(II i=0;i<N;i++){
2         S[i][i]=1;
3         if(i>=1) S[i][0]=0;
4         for(II j=1;j<i;j++) 
5             S[i][j]=(j*S[i-1][j]+S[i-1][j-1]+mod)%mod;
6     }

 

n个球可区分,m个盒子可区分

盒子不可为空:第二类斯特林数*阶乘数 S[n][m]*A[m]
盒子可以为空:m^n

由于盒子可以区分了,所以直接乘一个阶乘数就可以了,至于盒子可以为空的时候,每个球有m中选择,所以答案是m^n次方

其他和整数划分有关的问题:

  1.将n划分成最大数不超过k的划分数(完全背包物品1-k,背包容量n)

  2. 将n划分成若干奇正整数之和的划分数(完全背包物品小于n的奇数,背包容量为n)

  3. 将n划分成若干不同整数之和的划分数(0-1背包物品1-n,背包容量为n)

posted on 2017-10-03 01:02  xiaowuga  阅读(1643)  评论(0编辑  收藏  举报

导航