盒子与球问题(8种情况)

编号球是否相同盒子是否相同是否可以空盒
1相同相同
2相同相同
3不相同相同
4不相同相同
5相同不相同
6相同不相同
7不相同不相同
8不相同不相同

1.球相同,盒相同,有空盒

用f[i][j]记录i个球放到j个盒子的情况,首先可以对f[i][j]进行初始化的操作:

i=0的时候,0个球放到j个盒子里的情况始终为1;

i=1的时候,1个球放到j个盒子里的情况始终为1;

j=1的时候,i个球放到1个盒子里的情况始终为1;

其次对于之后的f[i][j]的情况:
i<j的时候:i个球放到j个盒子的情况与i个球放到j-1个盒子的情况相同

此时:f[i][j]=f[i][j-1];

i>=j的时候:可以由当前第j个盒子为空盒子,j个盒子全放然后处理i-j个球放j个盒子的情况得到;

此时:f[i][j]=f[i][j-1]+f[i-j][j];

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=20;
int f[N][N];
void pre(){
	memset(f,0,sizeof(f));
	for(int i=0;i<=15;i++){
		for(int j=0;j<=15;j++){
			if(i==0||i==1||j==1){
				f[i][j]=1;
			}
		}
	}
	for(int i=2;i<=15;i++){
		for(int j=1;j<=15;j++){
			if(i<j){
				f[i][j]=f[i][j-1];
			}
			else{
				f[i][j]=f[i][j-1]+f[i-j][j];
			}
		}
	}
} 
int main()
{
	pre();
	int n,m;
	while(cin>>n>>m){
		cout<<f[n][m]<<endl;
	}
	return 0;
}

2.球相同,盒相同,无空盒

这种情况可以由第一种情况推导出来:

当球的数量小于盒子的数量:有0种可能

当球的数量等于盒子的数量:有1种可能

当球的数量大于盒子的数量:先把每个盒子放上一个球,然后问题就是第一种情况

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=20;
int f[N][N];
void pre(){
	memset(f,0,sizeof(f));
	for(int i=0;i<=15;i++){
		for(int j=0;j<=15;j++){
			if(i==0||i==1||j==1){
				f[i][j]=1;
			}
		}
	}
	for(int i=2;i<=15;i++){
		for(int j=1;j<=15;j++){
			if(i<j){
				f[i][j]=f[i][j-1];
			}
			else{
				f[i][j]=f[i][j-1]+f[i-j][j];
			}
		}
	}
} 
int main()
{
	pre();
	int n,m;
	while(cin>>n>>m){
		if(n<m)cout<<0<<endl;
		else if(n==m)cout<<1<<endl;
		else{
			cout<<f[n-m][m]<<endl;
		}
	}
	return 0;
}

3.球不同,盒相同,无空盒

用f[i][j]记录i个球放到j个盒子的情况,首先可以对f[i][j]进行初始化的操作:

就是i个球放到i个盒子的可能性为1

f[i][j]可以由两种情况推导得到:

第i个球放到新开一个盒子,假设j就是那个新开的盒子,那么f[i][j]就是i-1个球放到j-1个盒子的情况

第i个球放到之前的盒子,那么结果可以由i-1个球放到j个盒子的情况得到,并且第i个球有j种选择

所以f[i][j]=f[i-1][j-1]+j*f[i-1][j];

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=20;
int f[N][N];
void pre(){
	memset(f,0,sizeof(f));
	for(int i=1;i<=15;i++){
		f[i][i]=1;
	}
	for(int i=2;i<=15;i++){
		for(int j=1;j<=15;j++){
			f[i][j]=f[i-1][j-1]+j*f[i-1][j];
		}
	}
} 
int main()
{
	pre();
	int n,m;
	while(cin>>n>>m){
		cout<<f[n][m]<<endl;
	}
	return 0;
}

4.球不同,盒相同,有空盒

这种情况可以由第三种情况得到

枚举盒子的个数,就可以知道所所有有空盒的情况

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=20;
int f[N][N];
void pre(){
	memset(f,0,sizeof(f));
	for(int i=1;i<=15;i++){
		f[i][i]=1;
	}
	for(int i=2;i<=15;i++){
		for(int j=1;j<=15;j++){
			f[i][j]=f[i-1][j-1]+j*f[i-1][j];
		}
	}
} 
int main()
{
	IOS
	int n,m;
	pre();
	while(cin>>n>>m){
		int ans=0;
		for(int i=1;i<=m;i++){
			ans+=f[n][i];
		}
		cout<<ans<<endl;
	}
	return 0;
}

5.球相同,盒不相同,无空盒

n个球间有n-1个空隙,m个盒子有m-1个空隙

答案就是在n-1个空隙中选m-1个

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=20;
int c(int n,int k){
	int sum1=1,sum2=1;
	for(int i=1;i<=k;i++){
		sum1*=i;
		sum2*=(n-k+i);
		if(sum2%sum1==0){
			sum2/=sum1;
			sum1=1;
		}
	}
	return sum2/sum1;
}
int main()
{
	IOS
	int n,m;
	while(cin>>n>>m){
		if(n<m)cout<<0<<endl;
		else{
			cout<<c(n-1,m-1)<<endl;
		}
	}
	return 0;
}

6.球相同,盒不相同,有空盒

可以先在每个盒子里塞一个球,那问题就变为第五种类型了

答案就是在n+m-1个空隙中选m-1个

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=20;
int c(int n,int k){
	int sum1=1,sum2=1;
	for(int i=1;i<=k;i++){
		sum1*=i;
		sum2*=(n-k+i);
		if(sum2%sum1==0){
			sum2/=sum1;
			sum1=1;
		}
	}
	return sum2/sum1;
}
int main()
{
	IOS
	int n,m;
	while(cin>>n>>m){
		cout<<c(n+m-1,m-1)<<endl;
	}
	return 0;
}

7.球不相同,盒不相同,无空盒

该情况就是第三种情况的结论下考虑盒子不同的问题

盒子不同的情况就是求它的一个排列

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=20;
ll f[N][N],b[N];
void pre(){
	for(int i=1;i<=15;i++){
		f[i][i]=1;
	}
	for(int i=2;i<=15;i++){
		for(int j=1;j<=15;j++){
			f[i][j]=f[i-1][j-1]+j*f[i-1][j];
		}
	}
	b[0]=1;
	for(int i=1;i<=15;i++){
		b[i]=b[i-1]*i;
	}
}
int main()
{
	IOS
	int n,m;
	pre();
	while(cin>>n>>m){
		cout<<b[m]*f[n][m]<<endl;
	}
	return 0;
}

8.球不相同,盒不相同,有空盒

每个球都有对应盒子的选择

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=20;
int main()
{
	IOS
	ll n,m;
	while(cin>>n>>m){
		ll ans=1;
        while(n){
        	if(n&1)ans=ans*m;
        	n>>=1;
        	m=m*m;
		}
        cout<<ans<<endl;
	}
	return 0;
}

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值