[分治] Codeforces#415 (Div. 1) 809A. Do you want a date?

来源:互联网 发布:mac怎么移除桌面图标 编辑:程序博客网 时间:2024/06/05 02:14

题意

给出一个n个元素的数集。
求这个集合的所有非空子集的权值和。一个集合 A 的权值定义为:maxi,jA |ij|

题解

集合的权值只由最大和最小的两个数决定,所以可以想到给 n 个数排序,题目转换为:
定义一个区间 [L,R] 的权值为 (a[R]a[L])2RL1 。求所有子区间权值和。
这个就分治乱搞就好了。

#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;} 
原创粉丝点击