【题解提供者】吴立强
解法
思路
可以证明,答案必定为:1,2,3,...,k−1,k,g1, 2, 3, ..., k-1, k, g1,2,3,...,k−1,k,g。其中有 g=n−∑i=1kg = n-\sum_{i=1}^kg=n−∑i=1k 成立。
首先,基于【贪心】思想,假设当前没用过的最小的数为 xxx,当前已用的数的和为 sumsumsum,那么如果满足 x+1≤(n−sum)−xx + 1 \le (n - sum) - xx+1≤(n−sum)−x(用 xxx 这个数,且用完后剩余的数不小于后一个没用过的数),那么从字典序的定义出发,没有理由不使用 xxx,也就是说拆分的数中必定包含 xxx。
利用上述推论,我们可以确定 kkk 的取值,且同时保证了拆分出序列满足“字典序”最小。
代码展示
#include <iostream>
using namespace std;
int main() {
int T; cin >> T;
while(T --) {
int n; cin >> n;
for(int i = 1; ; i ++) { /// 从 1 开始,依次拆分
if(i + i + 1 > n) break;
cout << i << ' ';
n -= i;
}
cout << n << ' ' << endl; /// 剩下的数不支持再拆分
}
}
算法分析
程序时间复杂度为 O(∑n)O(\sum \sqrt n)O(∑n),因为 kkk 的取值必定在 n\sqrt nn 级别(∑i=1k=k×(k+1)2\sum_{i=1}^k=\frac{k\times(k+1)}{2}∑i=1k=2k×(k+1))。