目录
题目描述
输入描述
输出描述
解析
完整代码
描述
一般来说,一个正整数可以拆分成若干个正整数的和。
例如,1=1,10=1+2+3+4 等。对于正整数 n 的一种特定拆分,我们称它为“优秀的”,当且仅当在这种拆分下,n 被分解为了若干个不同的 2 的正整数次幂。注意,一个数 x 能被表示成 2 的正整数次幂,当且仅当 x 能通过正整数个 2 相乘在一起得到。
例如,10=8+2=23+21 是一个优秀的拆分。但是,7=4+2+1=22+21+20 就不是一个优秀的拆分,因为 1 不是 2 的正整数次幂。
现在,给定正整数 n,你需要判断这个数的所有拆分中,是否存在优秀的拆分。若存在,请你给出具体的拆分方案。
输入描述
输入只有一行,一个整数 n,代表需要判断的数。
输出描述
如果这个数的所有拆分中,存在优秀的拆分。那么,你需要从大到小输出这个拆分中的每一个数,相邻两个数之间用一个空格隔开。可以证明,在规定了拆分数字的顺序后,该拆分方案是唯一的。
若不存在优秀的拆分,输出 -1
。
用例输入 1
6
用例输出 1
4 2
用例输入 2
7
用例输出 2
-1
提示
样例 1 解释
6=4+2=22+21 是一个优秀的拆分。注意,6=2+2+2 不是一个优秀的拆分,因为拆分成的 3 个数不满足每个数互不相同。
数据规模与约定
- 对于 20% 的数据,n≤10。
- 对于另外 20% 的数据,保证 n 为奇数。
- 对于另外 20% 的数据,保证 n 为 2 的正整数次幂。
- 对于 80% 的数据,n≤1024。
- 对于 100% 的数据,1≤n≤107。
来源
CSP-J
兄弟们啊,不是你们c++学不会,而是个别老师他教不对啊。
来,就这题你看着懵不懵,懵不懵!
看看老高平时是怎么教我的:
要解决这个问题,我们需要检查给定的正整数 n
是否能被拆分成若干个不同的 2 的正整数次幂的和。如果存在这样的拆分,我们需要输出从大到小的拆分序列;如果不存在,则输出 -1。
我们可以采用贪心算法来解决这个问题。从最大的 2 的次幂开始,逐步减去能够使用的最大次幂,直到 n
被完全分解或者无法继续分解。
具体步骤如下:
- 初始化一个空列表
result
来存储拆分结果。 - 从最大的 2 的次幂(不超过
n
)开始,尝试减去这个次幂,如果成功则将其加入result
。 - 重复上述步骤直到
n
为 0 或者无法再找到适合的 2 的次幂。 - 如果
n
最终为 0,则输出result
中的数;否则输出 -1。
下面是具体的 C++ 实现代码:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
void findExcellentPartition(int n) {
vector<int> result;
// 从最大的2的次幂开始尝试
for (int i = log2(n); i >= 0; --i) {
int powerOfTwo = 1 << i; // 2的i次幂
if (n >= powerOfTwo) {
n -= powerOfTwo;
result.push_back(powerOfTwo);
}
}
// 如果n被完全分解,输出result中的内容
if (n == 0) {
for (size_t i = 0; i < result.size(); ++i) {
if (i > 0) {
cout << " ";
}
cout << result[i];
}
cout << endl;
} else {
cout << -1 << endl;
}
}
int main() {
int n;
cin >> n;
findExcellentPartition(n);
return 0;
}
解释
-
输入处理:
- 读取输入的正整数
n
。
- 读取输入的正整数
-
算法实现:
- 使用
log2(n)
确定n
的最大可能 2 的次幂。 - 从最大的次幂开始,逐步尝试减去这个次幂的值,如果成功则将其添加到结果列表中。
- 最后检查
n
是否被完全分解,如果是则输出结果列表,否则输出 -1。
- 使用
-
输出:
- 如果存在优秀的拆分,按从大到小的顺序输出结果。
- 如果不存在优秀的拆分,输出 -1。
这样,我们就可以高效地判断并输出所需的拆分方案。
结束了!
对了,忘说了一句话:
要想c++成绩好,就来jiabei小课堂。
还有,点我主页,看我简介,别给那三个人点赞就完了