1 条题解

  • 0
    @ 2025-11-4 9:00:40

    1. 问题分析

    我们考虑光线在多层玻璃中的传播过程。当光线射到玻璃上时:

    • 一部分直接透射过去(ai%a_i\%
    • 一部分被反射回去(bi%b_i\%
    • 剩余的被吸收(100aibi%100-a_i-b_i\%

    由于存在反射,光线可能在两层玻璃之间来回反射,形成无穷级数。


    2. 动态规划思路

    dp[i]dp[i] 表示:当 1 单位光从上方垂直射入第 ii 层玻璃时,最终能从第 nn 层玻璃下方穿出的光的总量(包括所有反射路径的贡献)。

    我们要求的是 dp[1]dp[1]


    2.1 边界条件

    对于最后一层玻璃(i=ni = n):

    • 直接透射:an%a_n\%
    • 没有反射回来的光(因为后面没有玻璃了)

    所以:

    dp[n]=an100dp[n] = \frac{a_n}{100}

    2.2 状态转移

    考虑第 ii 层玻璃(1i<n1 \le i < n):

    1. 直接透射:光从第 ii 层上方射入,直接穿过第 ii 层,这部分光为 ai100\frac{a_i}{100},然后这些光会从第 i+1i+1 层上方射入,所以能穿出系统的量为:
    ai100×dp[i+1]\frac{a_i}{100} \times dp[i+1]
    1. 反射路径:光射入第 ii 层后,可能被反射回去(比例 bi100\frac{b_i}{100}),然后从第 i1i-1 层下方射入第 i1i-1 层(注意反射改变了方向),在第 i1i-1 层可能又被反射回来(此时从第 i1i-1 层下方反射回上方),再次射到第 ii 层上方,如此循环。

    为了处理这个无穷反射,我们引入另一个辅助状态:

    R[i]R[i] 表示:当 1 单位光从第 ii 层玻璃的下方垂直射入时,最终能从第 nn 层玻璃下方穿出的光总量。


    2.3 建立方程

    对于 dp[i]dp[i]

    • 直接穿过第 ii 层:ai100dp[i+1]\frac{a_i}{100} \cdot dp[i+1]
    • 被第 ii 层反射回去:bi100\frac{b_i}{100},然后从第 i1i-1 层下方射入第 i1i-1 层,得到 R[i1]R[i-1],再被第 i1i-1 层反射(从下方反射到上方)比例 bi1100\frac{b_{i-1}}{100},再射到第 ii 层上方,得到 dp[i]dp[i] 的贡献。

    这个过程形成无穷级数:

    X=dp[i]X = dp[i],则:

    $$X = \frac{a_i}{100} \cdot dp[i+1] + \frac{b_i}{100} \cdot R[i-1] \cdot \frac{b_{i-1}}{100} \cdot X + \frac{b_i}{100} \cdot R[i-1] \cdot \frac{b_{i-1}}{100} \cdot R[i-1] \cdot \frac{b_{i-1}}{100} \cdot X + \dots $$

    这是一个几何级数:

    $$X = \frac{a_i}{100} \cdot dp[i+1] + \frac{b_i}{100} \cdot R[i-1] \cdot \frac{b_{i-1}}{100} \cdot X \cdot \left(1 + \frac{b_{i-1}}{100} R[i-1] + \left(\frac{b_{i-1}}{100} R[i-1]\right)^2 + \dots \right) $$

    实际上更简单的推导是:

    光路:

    1. 直接透射 t1=ai100dp[i+1]t_1 = \frac{a_i}{100} dp[i+1]
    2. 或者:反射到左边 r=bi100r = \frac{b_i}{100},然后从 i1i-1 下方进入得到 R[i1]R[i-1],再反射(从 i1i-1 下方反射到上方)比例 bi1100\frac{b_{i-1}}{100},再进入第 ii 层上方,此时问题回到 dp[i]dp[i] 本身。

    所以:

    $$dp[i] = \frac{a_i}{100} dp[i+1] + \frac{b_i}{100} \cdot R[i-1] \cdot \frac{b_{i-1}}{100} \cdot dp[i] $$

    整理得:

    $$dp[i] \left(1 - \frac{b_i}{100} \cdot \frac{b_{i-1}}{100} \cdot R[i-1]\right) = \frac{a_i}{100} dp[i+1] $$$$dp[i] = \frac{\frac{a_i}{100} dp[i+1]}{1 - \frac{b_i}{100} \cdot \frac{b_{i-1}}{100} \cdot R[i-1]} $$

    2.4 类似地求 R[i]R[i]

    R[i]R[i] 表示 1 单位光从第 ii下方射入时,最终从第 nn 层下方穿出的光总量。

    • 直接透射(向上方向):ai100\frac{a_i}{100},然后从第 i1i-1 层下方进入得到 R[i1]R[i-1]
    • 或者:反射(向下方向)bi100\frac{b_i}{100},然后从第 i+1i+1 层上方进入得到 dp[i+1]dp[i+1],再反射(从 i+1i+1 上方反射到下方)比例 bi+1100\frac{b_{i+1}}{100},再进入第 ii 层下方,回到 R[i]R[i] 本身。

    所以:

    $$R[i] = \frac{a_i}{100} \cdot R[i-1] + \frac{b_i}{100} \cdot dp[i+1] \cdot \frac{b_{i+1}}{100} \cdot R[i] $$

    整理得:

    $$R[i] \left(1 - \frac{b_i}{100} \cdot \frac{b_{i+1}}{100} \cdot dp[i+1]\right) = \frac{a_i}{100} R[i-1] $$$$R[i] = \frac{\frac{a_i}{100} R[i-1]}{1 - \frac{b_i}{100} \cdot \frac{b_{i+1}}{100} \cdot dp[i+1]} $$

    2.5 边界条件

    • dp[n]=an100dp[n] = \frac{a_n}{100}
    • R[0]=1R[0] = 1(因为第 0 层不存在,光从第 1 层上方进入前,如果从第 0 层下方进入,相当于直接进入系统,全透过)
    • 注意 R[n]R[n] 也要算:光从第 nn 层下方进入,直接透射(向上)到第 n1n-1 层下方 R[n1]R[n-1],没有反射到右边的路径(因为右边是外部),所以:
    R[n]=an100R[n1]R[n] = \frac{a_n}{100} \cdot R[n-1]

    3. 模运算处理

    所有分数在模 M=109+7M = 10^9+7 下计算,需要用到模逆元。
    $\frac{p}{100} \equiv p \times \text{inv}(100) \pmod{M}$。


    4. 算法步骤

    1. 预处理 inv100=1001modMinv100 = 100^{-1} \bmod M
    2. 初始化 dp[n]=an×inv100modMdp[n] = a_n \times inv100 \bmod M
    3. 初始化 R[0]=1R[0] = 1
    4. i=n1i = n-111 计算:
      • 先算 R[i]R[i](需要 dp[i+1]dp[i+1] 已知)
      • 再算 dp[i]dp[i](需要 R[i1]R[i-1] 已知)
    5. 最后输出 dp[1]dp[1]

    注意 R[i]R[i]dp[i]dp[i] 可以交替计算。


    5. 样例验证

    样例 1:

    n=2
    a1=50, b1=20
    a2=80, b2=5
    

    计算: inv100=1001modM=700000005inv100 = 100^{-1} \bmod M = 700000005

    dp[2]=80×inv100=560000004dp[2] = 80 \times inv100 = 560000004

    R[1]R[1]: 分母 $= 1 - (20\times inv100) \times (5\times inv100) \times dp[2]$ 先算 20×inv100=14000000120\times inv100 = 1400000015×inv100=350000005\times inv100 = 35000000 乘积乘 dp[2]dp[2] 得 ... 最后 R[1]=(50×inv100×R[0])/分母R[1] = (50\times inv100 \times R[0]) / 分母
    再算 $dp[1] = (50\times inv100 \times dp[2]) / (1 - (20\times inv100) \times (5\times inv100) \times R[0])$

    最终 $dp[1] = 40 \times 100^{-1} / (1 - (20\times 100^{-1}) \times (5\times 100^{-1}))$
    0.4/(10.01)=0.4/0.99=40/990.4 / (1 - 0.01) = 0.4 / 0.99 = 40/99
    $40 \times 99^{-1} \bmod M = 40 \times 81818182 \bmod M = 858585865$,符合样例。


    6. 代码实现(C++)

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MOD = 1e9 + 7;
    const int MAXN = 500005;
    
    int n;
    int a[MAXN], b[MAXN];
    int dp[MAXN], R[MAXN];
    
    int modpow(int a, int e) {
        int res = 1;
        while (e) {
            if (e & 1) res = 1LL * res * a % MOD;
            a = 1LL * a * a % MOD;
            e >>= 1;
        }
        return res;
    }
    
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d%d", &a[i], &b[i]);
        }
        
        int inv100 = modpow(100, MOD - 2);
        
        dp[n] = 1LL * a[n] * inv100 % MOD;
        R[0] = 1;
        
        // 先计算 R[n]
        R[n] = 1LL * a[n] * inv100 % MOD * R[n-1] % MOD;
        
        for (int i = n - 1; i >= 1; i--) {
            // 计算 R[i]
            int denomR = (1 - 1LL * b[i] * inv100 % MOD * b[i+1] % MOD * inv100 % MOD * dp[i+1] % MOD + MOD) % MOD;
            R[i] = 1LL * a[i] * inv100 % MOD * R[i-1] % MOD * modpow(denomR, MOD - 2) % MOD;
            
            // 计算 dp[i]
            int denomD = (1 - 1LL * b[i] * inv100 % MOD * b[i-1] % MOD * inv100 % MOD * R[i-1] % MOD + MOD) % MOD;
            dp[i] = 1LL * a[i] * inv100 % MOD * dp[i+1] % MOD * modpow(denomD, MOD - 2) % MOD;
        }
        
        printf("%d\n", dp[1]);
        
        return 0;
    }
    

    7. 复杂度分析

    • 时间复杂度:O(nlogM)O(n \log M),因为每个状态计算需要模逆元(快速幂)。
    • 空间复杂度:O(n)O(n)

    这样我们就得到了一个可以处理 n5×105n \le 5\times 10^5 的高效解法。

    • 1

    信息

    ID
    4916
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者