求整数分解和数目的表达式

ominnc 2009-11-18 04:10:22
已知正整数n,
求n表示为其他正整数之和的所有可能性的表达式?
比如4可以表示为
4=1+3
4=2+2
4=1+1+2
4=1+1+1+1
所以整数4可以共有4种表示为其他正整数和的可能性。
求高手赐教!
...全文
118 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
lipeng8821 2009-11-19
  • 打赏
  • 举报
回复
太复杂了。。。想不出来
berryluo 2009-11-19
  • 打赏
  • 举报
回复
书名说错了,是《具体数学》这本书里
berryluo 2009-11-19
  • 打赏
  • 举报
回复
计算F(n)还是可以用我上面说的方法呀,同样是可以考虑1<=k<=n
F(n) = f(n)(1) + f(n)(2) + ... + f(n)(n)
其中f(n)(k) (1<=k<=n)表示把n分解为和式为n时加数中最大值不超过k的和式的个数
而f(n)(k) =f(n-k)(k) + f(n-k)(k-1) + ... + f(n-k)(1)
这里对于 f(i)(j),如果i < j,则f(i)(j) = 0;如果i == j ,则f(i)(j) = 1
复杂度为O(n^3),应该算是一个简单的动态规划吧
当然这里的式子应试是还可以简化的,《组合数学》里好像有这个题的公式和证明的
ominnc 2009-11-19
  • 打赏
  • 举报
回复
谢谢berryluo的热心答复,你的思路不错。
可是,我想得到的是计算所有可能性数目的计算公式F(n).
berryluo 2009-11-18
  • 打赏
  • 举报
回复
按上面我说的思路,写了个代码,供楼主参考,正确性没完全验证
得到7,8的和形式如下:
7
7 = 7
7 = 6 + 1
7 = 5 + 2
7 = 5 + 1 + 1
7 = 4 + 3
7 = 4 + 2 + 1
7 = 4 + 1 + 1 + 1
7 = 3 + 3 + 1
7 = 3 + 2 + 2
7 = 3 + 2 + 1 + 1
7 = 3 + 1 + 1 + 1 + 1
7 = 2 + 2 + 2 + 1
7 = 2 + 2 + 1 + 1 + 1
7 = 2 + 1 + 1 + 1 + 1 + 1
7 = 1 + 1 + 1 + 1 + 1 + 1 + 1
Press any key to continue
8
8 = 8
8 = 7 + 1
8 = 6 + 2
8 = 6 + 1 + 1
8 = 5 + 3
8 = 5 + 2 + 1
8 = 5 + 1 + 1 + 1
8 = 4 + 4
8 = 4 + 3 + 1
8 = 4 + 2 + 2
8 = 4 + 2 + 1 + 1
8 = 4 + 1 + 1 + 1 + 1
8 = 3 + 3 + 2
8 = 3 + 3 + 1 + 1
8 = 3 + 2 + 2 + 1
8 = 3 + 2 + 1 + 1 + 1
8 = 3 + 1 + 1 + 1 + 1 + 1
8 = 2 + 2 + 2 + 2
8 = 2 + 2 + 2 + 1 + 1
8 = 2 + 2 + 1 + 1 + 1 + 1
8 = 2 + 1 + 1 + 1 + 1 + 1 + 1
8 = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1
Press any key to continue


#include <stdio.h>
#include <string.h>

/**
* 把n为解为和式中最大值不超过k的和的形式,其中m<=n,
* 表示n中还剩余的没有分出去的值,和形式中至少有一个k
*/
void getSum(int n, int m, int k, char *str, int rightNum)
{
char outPut[1024];
char temp[20];
int loop;
if(n == m) {
sprintf(outPut, "%d = ", n);
} else {
strcpy(outPut, str);
}
if(m == k) {
printf("%s", outPut);
if(rightNum > 0) printf(" + ");
printf("%d\n", k);
} else {
if(rightNum > 0){
sprintf(temp, " + ");
strcat(outPut, temp);
}
sprintf(temp, "%d", k);
strcat(outPut, temp);
if(m - k >= k) getSum(n, m - k, k, outPut, rightNum + 1);//优先考虑有多个k的情形
loop = (m - k) >= k ? (k - 1) : (m - k);//接着考虑至少有一个k的情形
for(; loop >= 1; loop--) {
getSum(n, m - k, loop, outPut, rightNum + 1);
}
}
}

int main()
{
int n;
int loop;
char outPut[1024]={'\0'};
scanf("%d", &n);
for(loop = n; loop >= 1; loop--) {
//如果分解的和形式不包括n = n,这里初始化的时候改成loop = n - 1即可
getSum(n, n, loop, outPut, 0);
}
return 0;
}
berryluo 2009-11-18
  • 打赏
  • 举报
回复
对于n,考虑所有1<=k<=n的k,
考虑n的和表达式中最大值为k,那么此时问题转化为n-k的和表达式中最大值不超过k的问题,问题规模有所减少;把k的值从1取到n,这样就能递归地求出所有可能的和,不过至于这个的复杂度,我也不知道

33,028

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧