hdu 5481 Desiderium

本文探讨了一道算法题,要求计算一组区间选取任意子集时区间并集长度的期望值,并通过组合数学的方法求解。文章介绍了如何将原始区间转化为更小的单元进行重叠次数的统计,进而计算出每个区间的使用频率,最终得出答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

Desiderium

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 590    Accepted Submission(s): 227


Problem Description
There is a set of intervals, the size of this set is n.

If we select a subset of this set with equal probability, how many the expected length of intervals' union of this subset is?

We assume that the length of empty set's union is 0, and we want the answer multiply2n modulo 109+7.
 

Input
The first line of the input is a integer T, meaning that there are T test cases.

Every test cases begin with a integer n ,which is size of set.

Then n lines follow, each contain two integers l,r describing a interval of [l,r].

1n100,000.

1,000,000,000lr1,000,000,000.
 

Output
For every test case output the answer multiply 2n modulo 109+7.
 

Sample Input
2 1 0 1 2 0 2 1 3
 

Sample Output
1 7
Hint
For the second sample, the excepted length is $\frac{0+2+2+3}{4}=\frac{7}{4}$.





看到题目的第一时候我觉得是一题 dp,用dp[i]表示到i为止的集合的值,用一个标记来表示是否存在能重叠的集合;

时间复杂度可以用排序+线段树来优化,然后我发现因为x,y的范围过大,导致我开不出数组……

没思路了;

看了题解后发现用组合数来做;

把所有的集合化成一个个小的集合,统计每一个集合的重叠次数;

用重叠次数能计算出每个集合的使用次数;

使用次数乘上集合的宽度就是该集合能提供的值;

把所有的值加起来就是答案;


最让我无语的是,我好不容易从看每一题都是组合数的情况中走出来,没想到就遇到了组合数的题目;

组合数和dp在我的眼里真是傻傻分不清楚啊  orz……



代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define mod  1000000007
#define N 100007
#define LL __int64

using namespace std;

LL  p[N];
struct node
{
    LL x,y;
}data[N<<1];
LL sum[N];

int cmp(node a,node b)
{
    return a.x<b.x;
}
int main()
{
    int  T;
    scanf("%d",&T);
    p[0]=1;
    for(int i=1;i<N;i++)
        p[i]=(2*p[i-1] )%mod;
    while(T--)
    {
        int n;
        scanf("%d",&n);
        int i,j;
        for(i=1;i<=2*n;i+=2)
        {
            scanf("%I64d%I64d",&data[i].x,&data[i+1].x);
            data[i].y=1;
            data[i+1].y=-1;
        }
        sum[1]=p[n-1];
        for(i=2;i<=n;i++)
            sum[i]=(sum[i-1]+p[n-i])%mod;
        sort(data+1,data+2*n+1,cmp);
        LL ans=0;
        LL num=0;
        for(i=1;i<=2*n;i++)
        {
            num+=data[i].y;
            ans=(ans+sum[num]*(data[i+1].x-data[i].x)%mod)%mod;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值