问题描述
有一条数轴,还有一个区间的集合,集合大小为n。 现在等概率的从集合中选出集合的一个子集,求取出的子集的区间并集的期望长度。 空集的区间并长度被认为是0。
输入描述
输入文件包含多组数据,第一行为数据组数T。 对于每组数据,第一行为集合的大小n。 接下来的n行,每行两个数l , r代表集合内区间的左右端点坐标。 1≤n≤100,000. −1,000,000,000≤l≤r≤1,000,000,000.
输出描述
对于每组数据,输出期望乘2n 对 1000000007(109+7) 取模的结果。
输入样例
2 1 0 1 2 0 2 1 3
输出样例
1 7
Hint
对于第二个例子,期望为40+2+2+3=47。
找到递推方法。。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> using namespace std; typedef long long LL; const int maxn = 300005; const LL base = 1e9 + 7; int T, n, tot, l, r; struct point { int t, x; point(){} point(int t, int x) :t(t), x(x){} bool operator <(const point&a)const { if (x == a.x) return t > a.t; return x < a.x; } }f[maxn]; LL get(int x) { LL ans = 1; for (LL i = 2; x; x >>= 1) { if (x & 1) (ans *= i) %= base; i = i*i%base; } return ans - 1; } int main() { while (cin >> T) { while (T--) { scanf("%d", &n); for (int i = tot = 0; i < n; i++) { scanf("%d%d", &l, &r); f[tot++] = point(1, l); f[tot++] = point(-1, r); } sort(f, f + tot); LL ans = 0; for (int i = 0, j = 0, k = f[0].x; i < tot; i++) { (ans += (get(n - j) + 1)*get(j) % base*(f[i].x - k)) %= base; j += f[i].t; k = f[i].x; } printf("%I64d\n", ans); } } return 0; }