题解:洛谷 P2415 集合求和

【题目来源】

洛谷:P2415 集合求和 - 洛谷(luogu.com.cn)

【题目描述】

给定一个集合 \(s\)(集合元素数量 \(\le 30\)),求出此集合所有子集元素之和。

【输入】

集合中的元素(元素 \(\le 1000\)

【输出】

\(s\) 所有子集元素之和。

【输入样例】

2 3

【输出样例】

10

【核心思想】

  1. 问题分析:给定一个包含不超过 30 个元素的集合 \(s\),需要计算该集合所有子集的元素之和。每个元素在多少个子集中出现?对于包含 \(n\) 个元素的集合,每个元素出现在 \(2^{n-1}\) 个子集中(因为对于该元素之外的 \(n-1\) 个元素,每个都可以选择出现或不出现)。因此,所有子集元素之和 = 集合元素总和 \(\times 2^{n-1}\)。本质是组合数学问题,利用每个元素出现次数的对称性。

  2. 算法选择

    • 数学公式:直接计算元素总和 sum 和元素个数 n,答案即为 sum * 2^(n-1)。由于 \(n \le 30\)\(2^{29}\)long long 范围内,无需高精度。
    • 读入处理:使用 while(cin >> a) 循环读取所有元素,直到输入结束。
  3. 关键步骤

    • 读取与累加:使用循环读入每个元素 a,累加到 ans,并计数 k++
    • 计算答案ans *= pow(2, k-1)(或使用左移 1 << (k-1))。
    • 输出:输出 ans
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n)\)\(n\) 是元素个数。
    • 空间复杂度:\(O(1)\)
  5. 组合计数与幂运算

    • 核心公式:每个元素在所有子集中出现的次数为 \(2^{n-1}\),所以总和为 sum * 2^(n-1)
    • 幂运算pow(2, k-1) 返回 double,但结果在整数范围内,可直接用 1LL << (k-1) 更精确。
    • 适用场景:这类“集合子集求和”问题,核心是发现每个元素的出现次数规律,避免枚举所有子集。

【算法标签】

普及- #数学

【代码详解】

#include <bits/stdc++.h>  // 包含标准库头文件(万能头文件)
using namespace std;      // 使用标准命名空间

long long ans;           // 定义变量:存储最终结果(使用long long防止溢出)
int a, k = 0;            // 定义变量:a存储当前输入数字,k统计输入数字个数

int main()
{
    // 循环读取输入的数字,直到输入结束
    while (cin >> a)
    {
        ans += a;  // 累加所有输入数字的和
        k++;       // 统计输入数字的个数
    }

    // 计算结果:总和乘以2的(k-1)次方
    ans = (long long)ans * pow(2, k - 1);

    // 输出最终结果
    cout << ans << endl;

    return 0;  // 程序正常结束
}

【运行结果】

2 3
^Z
10
posted @ 2026-08-31 09:26  团爸讲算法  阅读(27)  评论(0)    收藏  举报