洛谷 P2404 自然数的拆分问题-普及-
题目描述
任何一个大于 111 的自然数 nnn,总可以拆分成若干个小于 nnn 的自然数之和。现在给你一个自然数 nnn,要求你求出 nnn 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。
输入格式
输入:待拆分的自然数 nnn。
输出格式
输出:若干数的加法式子。
输入输出样例 #1
输入 #1
7
输出 #1
1+1+1+1+1+1+1
1+1+1+1+1+2
1+1+1+1+3
1+1+1+2+2
1+1+1+4
1+1+2+3
1+1+5
1+2+2+2
1+2+4
1+3+3
1+6
2+2+3
2+5
3+4
说明/提示
数据保证,2≤n≤82\leq n\le 82≤n≤8。
solution
如果函数 f 将 n 拆解成最大加数不超过 m 的形式,则函数 f 可以写成递归形式即 f(n, m) = f(n, m-1) + f(n-m,m)
即 n 拆解成 不大于 m 的数相加的情况分为两种
- 没有 等于 m 的,f(n, m-1)
- 有等于 m 的 f(n-m,m)
代码
#include <sstream>
#include "iostream"
#include "math.h"
#include "algorithm"
#include "string.h"
#include "unordered_set"
#include "deque"
#include "stack"
#include "queue"
#include "vector"
#include "unordered_map"using namespace std;vector<string> res;void f(int n, int k, string s) { // 分解 n // 最大分解不超过 k//if (k > n) k = n;if (k == 1) {string ss;for (int i = 0; i < n; i++) ss += "1+";res.push_back(ss + s);return;}if (n == 1) {res.push_back("1+" + s);return;}for (int t = 1; t <= k; t++) {if (n - t > 0)f(n - t, t, to_string(t) + "+" + s);}if (n <= k) res.push_back(to_string(n) + "+" + s);
}int main() {int n;cin >> n;f(n, n, "");sort(res.begin(), res.end());for (int i = 0; i < res.size() - 1; i++) {cout << res[i].substr(0, res[i].size() - 1) << endl;}return 0;
}