P6146 [USACO20FEB]Help Yourself G 组合数学 DP
计算所有线段的所有子集的复杂度的和。
复杂度:线段集合的连通块个数。
连通块:不相交的并
考虑每个线段对前 i - 1个线段的贡献,若不选,则复杂度和不变,若选,则不相交的部分会贡献 2 ^ x 的复杂度。
故每次只需计算x的大小,x的大小可以建立前缀和数组来维护。
void Put(ll x) { if (x < 0) putchar('-'), x *= -1; if (x > 9) Put(x / 10); putchar(x % 10 + '0'); } struct Seg { int l, r; friend bool operator < (const Seg& a, const Seg& b) { if (a.l == b.l) return a.r < b.r; return a.l < b.l; } }; Seg s[maxn]; ll sum[2 * maxn]; int main() { int n = readint(); int x, y; for (int i = 0; i < n; i++) { x = readint(); y = readint(); s[i].l = x, s[i].r = y; sum[y]++; } sort(s, s + n); for (int i = 1; i < s[n - 1].r; i++) sum[i] += sum[i - 1]; ll pre = 1; ll res = 1; for (int i = 1; i < n; i++) { res = 2 * pre + ksm(2, sum[s[i].l - 1], MOD); res %= MOD; pre = res; } Put(res); }