今天我们来讲一讲球盒问题之不允许空盒
大家应该都听说过球盒问题,这类问题主要分为8种,首先,盒子可以空或不空,球可以相同或不同,盒子可以相同或不同。
所以一共有2×2×2=8种。
首先,我们来看第一种:
输入:7 3
输出:4
这题其实就是正整数拆分问题:
将整数n分成k份,且每份不能为空。任意两个方案不能相同(不考虑顺序)。 例如:n=7,k=3,下面三种分法被认为是相同的。 1,1,5;1,5,1;5,1,1; 问有多少种不同的分法。
同球同盒和这个一模一样。。
于是——状态转移方程就出来了!
来看第二种:
输入:4 2
输出:3
4个球放入假设把4个球分成两堆,就相当于把四个球分为两堆。
我们可以这样看:
◯◯◯|◯
◯◯|◯◯
◯|◯◯◯
所以,我们可以看到,n-1个空格,插入m-1个相同的板子,有几种?
答案显而易见,就是C(n-1,m-1)。
第三种:
这里要提到一个概念,叫斯特林数(第二类)。
查百度去……
输入:3 2
输出:3
来模拟一下:
一共其实就有三种。
那么如果要把第4个球插进去,又会怎样?
它可以在前面三个图里插入任何一列,有6种。
其实?还有!怎么?第4个球可以单独成一列!!
所以——推理后结论就出来了。
好了看最后一类:
这种和前面那个球不同盒子同很像。
为什么这么说??
因为这里只需要考虑盒子不同的情况!
盒子相同,盒子的所有排列方法为1种,有m个不同的盒子,排列方法就是m!
所以输出的时候乘以m的阶乘就可以了!!
最后来看四种情况的代码(需填空):
#include<bits/stdc++.h>
using namespace std;
int n,m,f[1009][1009];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)____1____;
for(int j=2;j<=m;j++)
for(int i=____2____;i<=n;i++)
____3____;
cout<<f[n][m];
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
cin>>n>>m;
if(____1____){
cout<<0<<endl;
return 0;
}
int ans=____2____;
for(int i=1;i<=m-1;i++){
ans*=____3____;
ans/=____4____;
}
cout<<ans<<endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
long long n,m;
int f[15][15];
int main(){
cin>>n>>m;
if(____1____){
cout<<0<<endl;
return 0;
}
for(long long i=1;i<=n;i++) f[i][1]=1;
for(long long j=2;j<=m;j++)
for(long long i=j;i<=n;i++)
____2____;
cout<<f[n][m]<<endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=16;
int n,m,S[N][N];
int main(){
cin>>n>>m;
if(____1____){
cout<<0;
return 0;
}
for(ll i=1;i<=n;i++)S[i][1]=1;
for(ll j=2;j<=m;j++)
for(ll i=j;i<=n;i++)
____2____;
ll ml=1;
____3____;
cout<<S[n][m]*ml;
return 0;
}
好了,本人这篇博客就到此了。