7-37 整数分解为若干项之和
将一个正整数N分解成几个正整数相加,可以有多种分解方法,例如7=6+1,7=5+2,7=5+1+1,…。编程求出正整数N的所有整数分解式子。
输入格式
每个输入包含一个测试用例,即正整数N (0<N≤30)。
输出格式
按照递增顺序输出N的所有整数分解式子。递增顺序是指:对于两个分解序列
输入样例
7
输出样例
7=1+1+1+1+1+1+1;7=1+1+1+1+1+2;7=1+1+1+1+3;7=1+1+1+2+2
7=1+1+1+4;7=1+1+2+3;7=1+1+5;7=1+2+2+2
7=1+2+4;7=1+3+3;7=1+6;7=2+2+3
7=2+5;7=3+4;7=7
分析与答案
这题我只想到了应该是递归的思想,但最后也没想出来,抄答案的(但分析是我的)。
下面的程序不仅有递归的元素,也有栈的元素在。程序建立了一个足够大的栈和栈顶指针,并建立了变量记录输出的次数和栈中元素的和(这些都作为全局变量存在)。在递归中,每一层对应的都是一个栈元素的插入循环,终点都是输入的正整数,而起点与栈中元素的位置和大小有关,每一层的起点都是前一层(也就是上一个栈元素)的当前数值,以此类推,这样可以保证输出可以满足题目要求的递增顺序。整个递归的思路如下:
- 如果当前记录的求和值与输入数值相等,则按照题目要求输出当前的求和式,再返回到上一层递归继续执行;
- 如果当前记录的求和值大于输入数值,则直接返回;
- 如果不是上述情况,那就将当前栈顶指针向前移动并放入数值(也就是执行入栈操作,具体是哪个值见上述分析),
sum
也加上对应数值,进入下一层递归; - 无论下一层递归的结果是直接返回还是输出了,此时栈顶的元素都要取出,
sum
也要重新减去对应数值。
到了栈中只有输入的数值n
时,对下一层的所有操作都会导致sum
值大于n
从而直接返回,因此在输出n=n
后整个递归过程就自动结束。
在输出时需要注意,每输出4次求和式就要换一次行,输出到最后n=n
时也是换行,其他时候则输出分隔符;
。
#include<stdio.h>
int N;
int s[31]; // 存放划分结果,这里用了比较简单地容器,数组,比我想象的要简单
int top = -1; // 数组指针
int count = 0; // 统计输出的次数
int sum = 0; // 拆分项累加和
void division (int i);
int main (){
scanf ("%d", &N);
division (1);
return 0;
}
void division (int i) {//拆分
if (sum == N) {
count ++;
printf("%d=", N);
int k;
for (k=0; k<top; k++) {
printf("%d+", s[k]);
}
if (count%4 == 0 || s[top] == N) {
printf("%d\n", s[top]);
} else {
printf("%d;", s[top]);
}
return;
} // 输出部分
if (sum > N) {
return;
}
for (int j=i; j<=N; j++) {
s[++top] = j;
sum += j;
division (j);
sum -= j;
top --;
} // 算法主体
}