LOJ#10018 数的划分

本文详细解析了整数分拆问题的算法实现,通过递归和动态规划两种方法求解将整数n分成k份的不同分法数量,适用于6≤n≤200,2≤k≤6的数据范围。

题目链接

题目描述

将整数 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];
}

用时:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值