题意
给出一个n个元素的数集。
求这个集合的所有非空子集的权值和。一个集合
A
的权值定义为:
题解
集合的权值只由最大和最小的两个数决定,所以可以想到给
n
个数排序,题目转换为:
定义一个区间
这个就分治乱搞就好了。
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL maxn=300015, MOD=1000000007;
int n,ans;
LL a[maxn],pw[maxn],inv_pw[maxn];
void Solve(int L,int R){
if(R-L+1<=1) return;
int mid=(L+R)>>1;
Solve(L,mid); Solve(mid+1,R);
LL sum1=0,sum2=0;
for(int i=mid+1;i<=R;i++) sum1=(sum1+pw[i])%MOD, sum2=(sum2+pw[i]*a[i]%MOD)%MOD;
for(int i=L;i<=mid;i++){
int res=inv_pw[i+1]* ((sum2+(MOD-a[i])*sum1%MOD)%MOD) %MOD;
ans=(ans+res)%MOD;
}
}
int main(){
// freopen("A.in","r",stdin);
// freopen("A.out","w",stdout);
pw[0]=inv_pw[0]=1;
for(int i=1;i<=300005;i++) pw[i]=pw[i-1]*2%MOD, inv_pw[i]=inv_pw[i-1]*((MOD+1)/2)%MOD;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);
sort(a+1,a+1+n);
Solve(1,n);
printf("%d\n",ans);
return 0;
}