概率+容斥

题目链接:https://codeforces.com/problemset/problem/1187/F

首先考虑单点贡献,是\(a[i] != a[i + 1]\)的时候产生的。而我们知道\(E(x_1) + E(x_2) = E(x_1 + x_2)\)

所以如果没有平方我们只需要计算单点期望然后加起来,这就是\(p[i] = 1 - \frac{x}{b[i]}\times \frac{1}{b[i+1]}\), \(b[i] = r[i] - l[i] + 1\)

有平方的时候分为三种情况考虑\(E(x_i)E(x_j)\)

  1. i=j ,不需要平方
  2. |i-j|>1,相互独立可以直接算
  3. |i-j|=1, 这里就需要容斥,但是注意到边界因为点1和0处固定产生贡献,所以初始化p[1] = 1, 且0,1,2三点是独立的,所以可以不需要容斥(这里卡了一下)

code:

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define int long long
const int N = 2e5 + 7, mod = 1e9 + 7;
int read() {
    int res = 0, f = 1;
    char c = getchar();
    while(c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 + c - '0';
        c = getchar();
    }
    return res * f;
}
int add(int a, int b) {
    return (a + b) % mod ;
}
int mul(int a, int b) {
    return 1ll * a * b % mod;
}
int sub(int a, int b) {
    return (a+mod-b)%mod;
}
int qpow(int x, int y) {
    int res = 1;
    while(y) {
        if (y & 1) res = mul(res, x);
        x = mul(x, x);
        y >>= 1;
    }
    return res;
}
struct Node {
    int l=0, r=0;
}a[N];
int p[N], q[N], pre[N], ans;
void calc(int i) {
    int tmp = 0;
    if (i - 2 > 0){
        tmp = max(0ll, min({a[i].r, a[i - 1].r, a[i - 2].r}) - max({a[i].l, a[i - 1].l, a[i - 2].l}));
        // cout << tmp << endl;
        tmp = mul(tmp, qpow(mul(mul(a[i].r - a[i].l, a[i - 1].r - a[i - 1].l), a[i - 2].r - a[i - 2].l), mod - 2));
        tmp = max(0ll, tmp);
    }
    int rc = add(sub(sub(1, q[i]), q[i - 1]), tmp);
    ans = add(ans, rc);
}
void solve() {
    int n;
    cin >> n;
    ans = 0;
    for (int i = 1; i <= n ;i++) cin >> a[i].l;
    for (int i = 1; i <= n ;i++) cin >> a[i].r, a[i].r++;
    p[1] = 1;
    pre[1] = 1;
    
    for (int i = 2; i <= n ;i++) {
        int tmp = max(0ll, min(a[i].r, a[i - 1].r) - max(a[i].l, a[i - 1].l));
        // cout << "!!!"<<tmp << ' ' << mul(a[i].r - a[i].l, a[i - 1].r - a[i - 1].l) << endl;
        q[i] = mul(tmp, qpow(mul(a[i].r - a[i].l, a[i - 1].r - a[i - 1].l), mod - 2));
        p[i] = sub(1, q[i]);
        pre[i] = add(pre[i - 1], p[i]);
        // cout << p[i] << endl;
    }
    // cout << pre[n] << endl;
    for (int i = 1; i <= n; i++) {
        int cus = pre[n];
        for (int j = max(1ll, i - 1); j <= min(n, i + 1); j++) {
            cus = sub(cus, p[j]);
            // cout <<j <<' '<<cus << endl;
        }

        ans = add(ans, mul(p[i], cus));
        // cout << cus << endl;
        if (i > 1) calc(i);
        if (i < n) calc(i + 1);
        ans = add(ans, p[i]);
    }
    // cout << mul(14, qpow(3, mod - 2)) << endl;;
    cout << ans << endl;
}
signed main(){
    int t = 1;
    while(t--){
        solve();
    }
}
posted @ 2025-05-14 22:24  lyrrr  阅读(15)  评论(0)    收藏  举报