hdu 5481 Desiderium

来源:互联网 发布:在职研究生网络教育 编辑:程序博客网 时间:2024/05/17 07:42
问题描述
有一条数轴,还有一个区间的集合,集合大小为nn。现在等概率的从集合中选出集合的一个子集,求取出的子集的区间并集的期望长度。空集的区间并长度被认为是00
输入描述
输入文件包含多组数据,第一行为数据组数TT。对于每组数据,第一行为集合的大小nn。接下来的nn行,每行两个数ll , rr代表集合内区间的左右端点坐标。1n1000001n100,000.1000000000lr10000000001,000,000,000lr1,000,000,000.
输出描述
对于每组数据,输出期望乘2n2n100000000710971000000007(109+7) 取模的结果。
输入样例
210 120 21 3
输出样例
17
Hint
对于第二个例子,期望为022347440+2+2+3=47
一个区间贡献值为该区间长度乘以有多少个线段子集覆盖了这个区间。如果一个区间被m个线段覆盖,那么他所贡献的值为区间长度乘以(2^n - 2^(n - m)),一共有2^n个子集,有2^(n - m)个子集没有覆盖到该区间,所以这两个数之差就是包含该区间的子集数。剩下的就是维护每个区间被线段覆盖次数。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int mod = 1e9 + 7;const int maxn = 1e5 + 10;int n, t;long long p[maxn];struct node{int x, cnt;bool operator< (const node& ano)const { if (x == ano.x) return cnt < ano.cnt; else return x < ano.x;}}seg[maxn * 2];int main(){p[0] = 1;for (int i = 1; i <= 1e5 + 5; i++) p[i] = (p[i - 1] * 2) % mod;scanf("%d", &t);while(t--){scanf("%d", &n);int l, r, now = 0;for (int i = 0; i < n; i++){scanf("%d%d", &l, &r);seg[now].x = l;seg[now++].cnt = 1;seg[now].x = r;seg[now++].cnt = -1;}sort(seg, seg + now);long long ans = 0;int pre = seg[0].x;int num = 0;for (int i = 0; i < now; i++){ans = (ans + ((seg[i].x - pre) * (p[n] - p[n - num] + mod)) % mod) % mod;pre = seg[i].x;num += seg[i].cnt;}printf("%lld\n", ans);}return 0;}


0 0
原创粉丝点击