《【CSP-J2020 入门】优秀的拆分( power)》 题解

目录

题目描述
输入描述
输出描述
解析
完整代码

描述

一般来说,一个正整数可以拆分成若干个正整数的和。

例如,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 被完全分解或者无法继续分解。

具体步骤如下:

  1. 初始化一个空列表 result 来存储拆分结果。
  2. 从最大的 2 的次幂(不超过 n)开始,尝试减去这个次幂,如果成功则将其加入 result
  3. 重复上述步骤直到 n 为 0 或者无法再找到适合的 2 的次幂。
  4. 如果 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;
}

 

解释

  1. ‌输入处理‌:

    • 读取输入的正整数 n
  2. ‌算法实现‌:

    • 使用 log2(n) 确定 n 的最大可能 2 的次幂。
    • 从最大的次幂开始,逐步尝试减去这个次幂的值,如果成功则将其添加到结果列表中。
    • 最后检查 n 是否被完全分解,如果是则输出结果列表,否则输出 -1。
  3. ‌输出‌:

    • 如果存在优秀的拆分,按从大到小的顺序输出结果。
    • 如果不存在优秀的拆分,输出 -1。

这样,我们就可以高效地判断并输出所需的拆分方案。

结束了!

对了,忘说了一句话:

要想c++成绩好,就来jiabei小课堂

还有,点我主页,看我简介,别给那三个人点赞就完了

### 关于2020CSP-J普及组试题Power优秀拆分问题的解题思路分析 对于给定正整数\( n \),判断其所有可能拆分中是否存在所谓的“优秀拆分”,并提供具体拆分方案的问题,在CSP-J 2020的相关题解中有提及[^1]。 #### 定义与理解 所谓“优秀拆分”是指一种特殊的加法分解方式,其中每个部分都由连续自然数组成。例如,如果一个数能够被表示为若干个连续自然数之和,则这种表达形式即视为该数的一个优秀拆分。 #### 判断条件 为了验证某个特定数值是否具有至少一组这样的优秀拆分,可以通过枚举中心位置或者边界来尝试构建满足上述定义的形式。当考虑奇数长度序列时,中间项决定了整个序列;而对于偶数长度的情况,则需关注两个相邻中间值之间的关系及其总和如何等于目标值的一半。 #### 构造算法实现 下面是一个简单的Python函数用于检测指定范围内任意整数是否有符合条件的拆分: ```python def find_excellent_partition(n): result = [] # 尝试不同起始点i直到sqrt(2*n)+1为止 i = 1 while True: sum_ = (i * (i - 1)) >> 1 if ((n - sum_) % i == 0 and (n - sum_) >= i): j = int((n - sum_) / i) temp_list = list(range(j, j+i)) result.append(temp_list) if (((i + 1) * i) >> 1) > n: break i += 1 return result if len(result)>0 else None print(find_excellent_partition(15)) ``` 此代码片段实现了寻找所有可能的优秀拆分数列的功能,并返回这些数列组成的列表。如果没有找到任何匹配的结果,则会返回`None`。 通过这种方法可以有效地解决问题中的核心挑战——识别哪些数字拥有至少一次有效的连续整数求和模式作为它们的一部分组成结构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值