2 条题解

  • 2
    @ 2026-10-25 22:15:02

    可恶的蠕虫,我连题都看不到。

    这么复杂的方法还有6个赞(angry)!

    思路

    我们根据期望的定义,有

    $$\text{期望}=\sum\text{概率}\cdot\text{价值}=\sum\frac{1}{\text{总方案数}}\cdot\text{价值}=\frac{1}{\text{总方案数}}\cdot\sum\text{价值}=\frac{\text{总价值}}{\text{总方案数}}$$

    总方案数是简单的(题目甚至都告诉你了),为 ∏i=1nri−li+1\prod_{i=1}^n r_i-l_i+1,难点在于求总价值。

    考虑固定最大值 hh,对于每个变量 xix_i,它对答案的贡献是 h−xi+1h-x_i+1。

    答案就是 ∑(h−xi,1+1)(h−xi,2+1)(h−xi,3+1)⋯\sum (h-x_{i,1}+1)(h-x_{i,2}+1)(h-x_{i,3}+1)\cdots

    这个怎么求呢?

    先考虑简单情况:

    $$x_1\text{ }x_2\text{ }x_3\\y_1\text{ }y_2\\z_1\text{ }z_2$$

    在 xx 中选一个、yy 中选一个、zz 中选一个,相乘再求和,这个东西我们会这样算:

    $$ans=\\x_1y_1z_1+x_1y_1z_2+x_1y_2z_1+x_1y_2z_2+\\ x_2y_1z_1+x_2y_1z_2+x_2y_2z_1+x_2y_2z_2+\\ x_3y_1z_1+x_3y_1z_2+x_3y_2z_1+x_3y_2z_2$$

    然后再乘法分配律一下,

    $$ans=x_1y_1z_1+x_1y_1z_2+\cdots+x_3y_2z_2\\=(x_1+x_2+x_3)(y_1+y_2)(z_1+z_2)$$

    我们记 f(h)f(h) 表示 ∀xi≤h\forall x_i\leq h 的答案,根据刚才的公式,

    $$f(h)=\prod_{i=1}^n\sum_{x_i=l_i}^{\min(r_i,h)}(h-x_i+1)$$

    ∑xi=limin⁡(ri,h)(h−xi+1)\sum_{x_i=l_i}^{\min(r_i,h)}(h-x_i+1) 是可以通过等差数列求和 Θ(1)\Theta(1) 求的,所以我们可以在 Θ(n)\Theta(n) 求出 f(h)f(h),那我们再容斥一下就可以求出最大值恰好为 hh 时的答案,为 f(h)−f(h−1)f(h)-f(h-1),即去掉 ∀xi<h\forall x_i<h 的答案

    代码

    复杂度:外层枚举 hh,里面 Θ(2n)\Theta(2n) 求出 f(h)f(h) 和 f(h−1)f(h-1),总时间复杂度为 Θ((maxr−maxl)⋅n)\Theta((maxr-maxl)\cdot n)。

    • st 和 ed 分别表示 hh 的最小值和最大值,显然 st=max⁡i=1nlist=\max_{i=1}^n l_i (因为 maxi=1nxmax_{i=1}^n x 至少这么多),ed=max⁡i=1nried=\max_{i=1}^n r_i (因为 maxi=1nxmax_{i=1}^n x 至多这么多);

    • now 表示 x≤hx\leq h 的价值总和 pre 表示 x≤h−1x\leq h-1 的价值总和;

    • calc 表示 ∑i=lrh−x+1\sum_{i=l}^r h-x+1 的值。

    // sequence
    #include <iostream>
    using namespace std;
    
    const int MOD = 1e9 + 7;
    int n, l[1005], r[1005], sum, cnt = 1, st, ed;
    
    int quick_pow(int x, int y) {
        int res = 1;
        while (y) {
            if (y & 1) res = 1ll * res * x % MOD;
            x = 1ll * x * x % MOD;
            y >>= 1;
        }
        return res;
    }
    
    int calc(int l, int r, int h) { // sum of (h - x + 1), x in [l, r]
        int sum_x = 1ll * (l + r) * (r - l + 1) / 2ll % MOD;
        return (1ll * (r - l + 1) * (h + 1) % MOD - sum_x + MOD) % MOD;
    }
    
    int main() {
        freopen("sequence.in", "r", stdin);
        freopen("sequence.out", "w", stdout);
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            scanf("%d%d", &l[i], &r[i]);
            cnt = 1ll * cnt * (r[i] - l[i] + 1) % MOD;
            st = max(st, l[i]);
            ed = max(ed, r[i]);
        }
        for (int h = st; h <= ed; ++h) {
            int now = 1, pre = 1;
            for (int i = 1; i <= n; ++i) {
                now = 1ll * now * calc(l[i], min(r[i], h), h) % MOD;
                pre = 1ll * pre * calc(l[i], min(r[i], h - 1), h) % MOD;
            }
            sum = (sum + (now - pre + MOD) % MOD) % MOD;
        }
        int ans = 1ll * sum * quick_pow(cnt, MOD - 2) % MOD;
        printf("%d\n", ans);
        return 0;
    }
    

    信息

    ID
    2817
    时间
    1000ms
    内存
    128MiB
    难度
    6
    标签
    (无)
    递交数
    12
    已通过
    8
    上传者