主题:[讨论]求正整数n划分为k个数的和的划分数
hitsoft
[专家分:280] 发布于 2007-03-13 14:35:00
比如5,如果划分为2个数的和,可以有2种划分:1+4,2+3.
输入: 5 2
输出: 2
这题大家有什么想法呀,我想了挺久,都没想出来。
用组合去解,很容易把重复的也算进去。如果用DP,又不知道该怎么DP,晕了。
回复列表 (共14个回复)
沙发
hitsoft [专家分:280] 发布于 2007-03-13 14:37:00
哦,K个数,指的也是正整数.
板凳
rickone [专家分:15390] 发布于 2007-03-13 17:11:00
组合学里的东西 看我的兴趣小组
3 楼
euc [专家分:4310] 发布于 2007-03-13 19:26:00
这个能用DP吗
4 楼
rickone [专家分:15390] 发布于 2007-03-13 22:36:00
DP?
DP是求最优解,这里不是最优化问题,是组态的记数。
5 楼
DataStructureFan [专家分:0] 发布于 2007-03-14 15:08:00
首先先创建一个集合,元素个数为N-1,并且给其赋初值1、2、… N-1,这样就构成了一个比N小的正整数的所有集合,标记这个集合为A,那么就可以通过求这个A集合的元素个数为K的子集来实现求解。求这个A集合K个元素的子集合的方法可以通过回朔法求得。算法需要额外的N - 1个单位空间和2的K次方的时间复杂度
6 楼
hitsoft [专家分:280] 发布于 2007-03-14 21:43:00
回复5楼的:
你提到的解法跟我提的问题不一样.我是一个正整数的划分数,而不是求一集合里K个元素子集的个数。如果硬要按你的算法,复杂度就够呛,还得进一步筛选符合条件的,根本是不可能的事.
回复2楼的:
"一个整数n拆分成恰好m部分的拆分数等于这个整数n拆分成最大部分为m的拆分数."
我去看了下,大有所获,谢谢!这样求解这个问题就可以转换成DP来解了。
a[n][k]表示整数N划分为最大数不超过K的划分数.
a[n][k]=a[n-k][k]+a[n][k-1];
则原问题就是求解a[n-k][k]了.这样就很容易解决了!
7 楼
rickone [专家分:15390] 发布于 2007-03-14 22:09:00
可以说,没有min和max就不是DP,运筹学里的规划方法都是求最优决策。
8 楼
wangfangbob [专家分:380] 发布于 2007-03-15 00:16:00
貌似和金山公司的那道分苹果一样
9 楼
ttuurr [专家分:70] 发布于 2007-03-16 13:31:00
// 正整数n划分为k个正整数的和的划分数
// 使用递归
#include <iostream>
using namespace std;
const int MAXK=10;
int n, k, total, a[MAXK];
void print() {
int i=0;
while(true) {
cout<<a[i];
if(a[++i] != 0)
cout<<'+';
else
break;
}
cout<<endl;
}
void divide(int n, int k, int min, int index) {
while(min<=n/k) {
if(k>1) {
a[index]=min;
divide(n-min,k-1,min,index+1);
}
else {
a[index]=n;
total++;
print();
return;
}
min++;
}
}
int main() {
while(true) {
cout<<"请输入n、k"<<endl;
do {
cin>>n>>k;
} while(n<0 || k<0);
if(n==0 || k==0)
break;
memset(a,0,sizeof(a));
total=0;
divide(n,k,1,0);
cout<<"total="<<total<<endl<<endl;
}
}
10 楼
rickone [专家分:15390] 发布于 2007-03-16 21:18:00
[quote]a[n][k]表示整数N划分为最大数不超过K的划分数.
a[n][k]=a[n-k][k]+a[n][k-1];
则原问题就是求解a[n-k][k]了.这样就很容易解决了![/quote]
这个公式不错,边界是a[n][1]=a[1][n]=a[0][n]=1,n*k次加法完成。
我来回复