题目
给定一个集合 s s s(集合元素数量 ≤ 30 \le 30 ≤30),求出此集合所有子集元素之和。
输入格式
集合中的元素(元素 ≤ 1000 \le 1000 ≤1000)
输出格式
s s s 所有子集元素之和。
样例 #1
样例输入 #1
2 3
样例输出 #1
10
提示
【样例解释】
子集为: ∅ , { 2 } , { 3 } , { 2 , 3 } \varnothing, \{ 2 \}, \{ 3 \}, \{ 2, 3 \} ∅,{2},{3},{2,3},和为 2 + 3 + 2 + 3 = 10 2 + 3 + 2 + 3 = 10 2+3+2+3=10。
【数据范围】
对于 100 % 100 \% 100% 的数据, 1 ≤ ∣ s ∣ ≤ 30 1 \le \lvert s \rvert \le 30 1≤∣s∣≤30, 1 ≤ s i ≤ 1000 1 \le s_i \le 1000 1≤si≤1000, s s s 所有子集元素之和 ≤ 10 18 \le {10}^{18} ≤1018。
解法
这个题目是可以单纯通过找规律来获得公式的. 我们不妨从1个元素开始列举一下:
- { 1 } \{1\} {1} 可以发现只有一个子集, 那么求和就是 1 × 1 1\times1 1×1
- { 1 , 2 } \{1, 2\} {1,2} 可以列举一下, { 1 } \{1\} {1}, { 2 } \{2\} {2}, { 1 , 2 } \{1, 2\} {1,2}, 求和就是6, 可以发现元素出现的次数都是2, 也就可以转换为公式 { 2 × ( 1 + 2 ) } \{2\times(1 + 2)\} {2×(1+2)}
- { 1 , 2 , 3 } \{1, 2, 3\} {1,2,3} 一样, 列举出来: { 1 } \{1\} {1}, { 2 } \{2\} {2}, { 3 } \{3\} {3}, { 1 , 2 } \{1, 2\} {1,2}, { 1 , 3 } \{1, 3\} {1,3}, { 2 , 3 } \{2, 3\} {2,3}, { 1 , 2 , 3 } \{1, 2, 3\} {1,2,3}, 发现刚好每个元素都出现了4次, 那么就可以转换为: { 4 × ( 1 + 2 + 3 ) } \{4 \times(1 + 2 + 3)\} {4×(1+2+3)}
如果你的数感好, 应该已经发现规律了:
- 有1个元素的时候, 所有子集求和为1 * 所有元素的和
- 有2个元素的时候, 所有子集求和为2 * 所有元素的和
- 有3个元素的时候, 所有子集求和为4 * 所有元素的和
- …
- 有n个元素的时候, 所有子集求和为 2 n − 1 × s u m ( a r r a y ) 2^{n - 1} \times sum(array) 2n−1×sum(array)
既然通项公式有了, 那么写为代码就很简单了:
#include <bits/stdc++.h>
using namespace std;
int main() {
string s;
getline(cin, s);
long long a;
stringstream ss(s);
// 两个计数变量
long long counter = 0;
long long mySum = 0;
while (ss >> a) {
counter++;
mySum += a;
}
cout << fixed << setprecision(0) << pow(2, counter - 1) * mySum << endl;
return 0;
}
最后使用
fixed << setprecision(0)
是用来防止输出科学计数法的使用
long long
来防止溢出
最后, 恭喜 AC !