题目描述
将整数 n 分成 k 份,且每份不能为空,问有多少种不同的分法。当 n=7, k=3 时,下面三种分法被认为是相同的:1,1,5; 1,5,1; 5,1,1
输入格式
一行两个数 n , k。
输出格式
一行一个整数,即不同的分法数。
样例
样例输入
7 3
样例输出
4
样例解释
四种分法为:1,1,5;1,2,4;1,3,3;2,2,3。
数据范围与提示
6≤n≤200, 2≤k≤6。
将整数n分成k份就相当于将n个苹果放入k个篮子里且每个篮子里都至少放入一个苹果,即将(n-k)个苹果放入k个篮子且允许有的篮子为空。
接下来考虑将m个苹果放入k个篮子里(允许有的篮子为空),设f(m,k)为m个苹果放入k个篮子里(允许有的篮子为空)的方法数目;
当k>m时,(k-m)个篮子必定是空的,这些多余的篮子可忽略:if(k>m) f(m,k)=f(m,m);
当k<=m时,又可分为两种情况,①有一个篮子为空时,这个多余的篮子可忽略:f(m,k)=f(m,k-1),多于一个篮子为空的情况由f(m,k-1)计算;②全部篮子不为空时,相当于可以至少从每个篮子里拿出一个苹果:f(m,k)=f(m-k,k);
即:if(k<=m) f(m,k)=f(m,k-1)+f(m-k,k);
边界条件:当m==0时,无方法,定义f=1;当n==1时,所有苹果放在一个篮子里,f=1;
递归:
//优快云博客:https://blog.youkuaiyun.com/qq_40889820
#include<iostream>
#include<sstream>
#include<fstream>
#include<algorithm>
#include<string>
#include<cstring>
#include<iomanip>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<map>
#define mem(a,b) memset(a,b,sizeof(a))
#define random(a,b) (rand()%(b-a+1)+a)
#define e 2.71828182
#define Pi 3.141592654
using namespace std;
int f(int m,int k)
{
if(m==0||k==1) return 1;
if(k>m) return f(m,m);
return f(m-k,k)+f(m,k-1);
}
int main()
{
int n,k;
cin>>n>>k;
cout<<f(n-k,k);
}
用时:
动态规划:
//优快云博客:https://blog.youkuaiyun.com/qq_40889820
#include<iostream>
#include<sstream>
#include<fstream>
#include<algorithm>
#include<string>
#include<cstring>
#include<iomanip>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<map>
#define mem(a,b) memset(a,b,sizeof(a))
#define random(a,b) (rand()%(b-a+1)+a)
#define e 2.71828182
#define Pi 3.141592654
using namespace std;
int main()
{
int n,k;
int f[201][7];
cin>>n>>k;
mem(f,0);
for(int i=1;i<=k;i++) f[0][i]=1;
for(int i=1;i<=n-k;i++) f[i][1]=1;
for(int i=1;i<=n-k;i++)
{
for(int j=1;j<=k;j++)
{
if(j>i) f[i][j]=f[i][i];
else f[i][j]=f[i-j][j]+f[i][j-1];
}
}
cout<<f[n-k][k];
}
用时: