将一个正整数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,⋯,ni=mi,但是ni+1<mi+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,则改变下一项的大小;如果等于N,则输出;如果大于N, 则返回。做了挺久的,思路也转换到递归和全局数组上去了。(这是别人的思路,不过跟我的想法大同小异)上一次写递归,除了最近写的求最大公约数,大概是很久以前写的八皇后问题了吧,感觉一点都不会写了。下面是我写的代码,在网上比较了一番,感觉我写的还是太麻烦了。不过还是厚脸皮贴在下面吧!
#include<iostream>
using namespace std;
void ChangeArray(int m, int left);
int num[30];
int N, cnt = 0, k; //cnt:输出的表达式数量, 用于控制输出换行符 k:当前控制分解式的第几个数
int main(){
int i;
cin >> N;
for(i = 0; i < N; i++)
num[i] = 1;
k = N - 1;
cout << N << '=';
for(i = 0; i < N; i++){
if(i != N - 1) cout << "1+";
else{
cout << "1";
if(num[0] != N) cout << ';';
}
}
cnt++;
while(k >= 0){
ChangeArray(k, N - k);
k--;
}
}
void ChangeArray(int k, int left){
//改变数组k位及k位以后
int i, j, max;
if(k != 0){
max = num[k - 1] > 2 ? num[k - 1] : 2;
for(i = max; i <= left; i++){
num[k] = i;
ChangeArray(k + 1, left - i);
}
}else{
for(i = 2; i <= left; i++){
num[k] = i;
ChangeArray(k + 1, left - i);
}
}
//输出
if(left == 0){
cnt++;
cout << N << '=';
for(i = 0; i < k; i++){
if(i != k - 1) cout << num[i] << '+';
else cout << num[i];
}
if(num[0] != N){
if(cnt % 4 == 0 ) cout << '\n';
else cout << ';';
}
}
//返回
return ;
}