统计集合
题目链接:ybt高效进阶 21163 / 150A
题目大意
给你一个集合,问你它每个子集合的分数和。 将集合分数定义为最大数减去最小数。 确保集合中无重复元素。
思路
我们发现最大数和最小数可以分开计算。
然后我们可以列举集合中最大或最小的元素,然后看看有多少这样的子集合。 我们以最小元素为例:这个元素一定要选择,比它小的不能选择,比它大的不能选择,那个数字就是 2 ( 比 它 小 的 元 素 个 数 ) 2^{(比它小的元素数)} 2(比它小的元素个数)。 然后我们排序,预处理 2 x 2^x 2x,就可以 O ( n ) O(n) O(n) 啦。
代码
#include<map> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define mo 1000000007 using namespace std
;
int n
, a
[
1000001
]
; ll ans
, two
[
1000001
]
;
int
main
(
)
{
// freopen("sum.in", "r", stdin);
// freopen("sum.out", "w", stdout);
scanf
(
"%d"
,
&n
)
;
for
(
int i
=
1
; i
<= n
; i
++
)
scanf
(
"%d"
,
&a
[i
]
)
;
sort
(a
+
1
, a
+ n
+
1
)
; two
[
0
]
=
1
;
for
(
int i
=
1
; i
<= n
; i
++
) two
[i
]
=
(two
[i
-
1
]
*
2
)
% mo
;
for
(
int i
=
1
; i
<= n
; i
++
)
{
ans
=
(ans
+
1ll
* a
[i
]
* two
[i
-
1
]
)
% mo
;
//作为最大 ans
=
(
(ans
-
1ll
* a
[i
]
* two
[n
- i
]
)
% mo
+ mo
)
% mo
;
//作为最小
}
printf
(
"%lld"
, ans
)
;
return
0
;
}