7-37 整数分解为若干项之和 (20 分)
将一个正整数N分解成几个正整数相加,可以有多种分解方法,例如7=6+1,7=5+2,7=5+1+1,…。编程求出正整数N的所有整数分解式子。
输入格式:
每个输入包含一个测试用例,即正整数N (0<N≤30)。
输出格式:
按递增顺序输出N的所有整数分解式子。递增顺序是指:对于两个分解序列N1={n1,n2,⋯}和N2={m1,m2,⋯},若存在i使得n1=m1,⋯,n**i=m**i,但是n**i+1<m**i+1,则N1序列必定在N2序列之前输出。每个式子由小到大相加,式子间用分号隔开,且每输出4个式子后换行。
输入样例:
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
解题思路:
先将第一种情况存入数组,对于n==7而言,则z[1~7]=1;用一个变量来记录位数,每次计算数组总和(有效位)时,
判断sum和n的关系:
- sum==n : 打印,有效位减一,当前有效位的值+1;
- sum < n : 有效位加一,把旧有效位的值复制给新有效位的值;
- sum > n : 有效位减一,当前有效位的值+1;
代码如下:
#include<stdio.h>
int main() {
int n;
scanf("%d", &n);
int z[31] = { -1 }; //最大n为31,z[0] = -1,用于后续循环判断
for (int i = 1; i <= n; i++)
z[i] = 1; //初始化数组
int flag = n; //记录有效位
int sum = 0; //记录总和
int cnt = 0; //打印换行
while (z[0] != 0) { //最后一次打印是n=n,进一位就变成了z[0]==0
for (int i = 1; i <= flag; i++)
sum += z[i]; //计算总和
if (sum == n) {
printf("%d=", n);
for (int i = 1; i <= flag; i++) {
if (i != flag) printf("%d+", z[i]);
else {
//每行的最后一个无分号,最后一次打印也无分号
if (cnt%4==3||flag==1) printf("%d", z[i]);
else printf("%d;", z[i]);
}
}
cnt++;
if (cnt % 4 == 0) printf("\n");
z[--flag]++; //有效位减一,当前有效位的值+1
}
else if (sum > n) z[--flag]++; //有效位减一,当前有效位的值+1
else z[++flag] = z[flag - 1]; //有效位加一,把旧有效位的值复制给新有效位的值
sum = 0; //清零
}
return 0;
}