o1 爆切 F 题

Correct Approach:

  1. Modeling the Problem as a Markov Chain:

    • States: Each state represents the current word being spoken (from 1 to ( n )).
    • Transitions:
      • From state 1:
        • Move to state 2 with probability ( \frac{a_1}{a_1 + b_1} ).
        • Stay at state 1 with probability ( \frac{b_1}{a_1 + b_1} ).
      • From state ( i ) (( 2 \leq i \leq n-1 )):
        • Move to state ( i+1 ) with probability ( \frac{a_i^2}{a_i^2 + 2a_i b_i + b_i^2} ).
        • Stay at state ( i ) with probability ( \frac{2a_i b_i}{a_i^2 + 2a_i b_i + b_i^2} ).
        • Move back to state ( i-1 ) with probability ( \frac{b_i^2}{a_i^2 + 2a_i b_i + b_i^2} ).
      • From state ( n ):
        • Absorbing state (stop speaking).
  2. Setting Up the System of Linear Equations:

    • Let ( E[i] ) denote the expected number of words spoken starting from word ( i ).
    • For ( i < n ): [ E[i] = 1 + P(i \rightarrow i-1) \cdot E[i-1] + P(i \rightarrow i) \cdot E[i] + P(i \rightarrow i+1) \cdot E[i+1] ]
    • Rearranging: [ (1 - P(i \rightarrow i)) \cdot E[i] - P(i \rightarrow i-1) \cdot E[i-1] - P(i \rightarrow i+1) \cdot E[i+1] = 1 ]
    • For ( i = n ): [ E[n] = 1 ]
    • This forms a tridiagonal system which can be efficiently solved using the Thomas Algorithm.
  3. Implementing the Thomas Algorithm:

    • Forward Sweep:
      • Modify the coefficients to eliminate the lower diagonal.
    • Backward Substitution:
      • Solve for the expected values starting from the last equation.
  4. Handling Modular Arithmetic:

    • Since the problem requires the answer modulo ( 10^9 + 7 ), we must perform all calculations under this modulus.
    • Fractions are handled using modular inverses.
  5. Edge Cases:

    • If ( n = 1 ), the expected number of words spoken is simply 1.

Final Implementation:

Below is the corrected C++ implementation based on the above reasoning. The key correction involves properly handling the last word by adjusting the condition in the loop that sets up the tridiagonal system.

#include <bits/stdc++.h>
using namespace std;


typedef long long ll;


const int MOD = 1000000007;


// Fast exponentiation to compute x^e mod MOD
ll powmod_func(ll x, ll e, ll mod) {
    ll res = 1;
    x %= mod;
    if(x < 0) x += mod;
    while(e > 0){
        if(e & 1){
            res = res * x % mod;
        }
        x = x * x % mod;
        e >>=1;
    }
    return res;
}


int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    if(n ==1){
        cout << "1";
        return 0;
    }
    vector<ll> a(n-1), b(n-1);
    for(int i=0;i<n-1;i++) cin >> a[i];
    for(int i=0;i<n-1;i++) cin >> b[i];
    // Initialize A, B, C, D
    // A: lower diagonal, size n-1
    // B: main diagonal, size n-1
    // C: upper diagonal, size n-1
    // D: constants, size n-1
    vector<ll> A(n-1,0), B_coeff(n-1,0), C(n-1,0), D(n-1,0);
    for(int i=0;i<n-1;i++){
        if(i ==0){
            // i=0 corresponds to word1
            ll a1 = a[i];
            ll b1 = b[i];
            ll denom = (a1 + b1) % MOD;
            ll inv_denom = powmod_func(denom, MOD-2, MOD);
            // P_forward = a1 / (a1 + b1)
            ll P_forward = a1 * inv_denom % MOD;
            // P_stay = b1 / (a1 + b1)
            ll P_stay = b1 * inv_denom % MOD;
            // Set up equation: (1 - P_stay) * E0 - P_forward * E1 =1
            B_coeff[i] = (1 - P_stay + MOD) % MOD; // 1 - P_stay
            C[i] = (MOD - P_forward) % MOD; // -P_forward
            D[i] =1;
        }
        else{
            ll ai = a[i];
            ll bi = b[i];
            ll denom = (ai * ai % MOD + 2 * ai % MOD * bi % MOD + bi * bi % MOD) % MOD;
            ll inv_denom = powmod_func(denom, MOD-2, MOD);
            // P_forward = a_i^2 / denom
            ll P_forward = (ai * ai % MOD) * inv_denom % MOD;
            // P_stay = 2 * a_i * b_i / denom
            ll P_stay = (2 * ai % MOD * bi % MOD) * inv_denom % MOD;
            // P_backward = b_i^2 / denom
            ll P_backward = (bi * bi % MOD) * inv_denom % MOD;
            if(i < n-2){
                // Normal variable
                A[i] = (MOD - P_backward) % MOD; // -P_backward
                B_coeff[i] = (1 - P_stay + MOD) % MOD; // 1 - P_stay
                C[i] = (MOD - P_forward) % MOD; // -P_forward
                D[i] =1;
            }
            else{
                // Last variable (i = n-2 corresponds to word n-1)
                A[i] = (MOD - P_backward) % MOD; // -P_backward
                B_coeff[i] = (1 - P_stay + MOD) % MOD; // 1 - P_stay
                C[i] =0; // No upper diagonal for the last equation
                // D[i] =1 + P_forward * E_n, where E_n =1
                D[i] = (1 + P_forward) % MOD;
            }
        }
    }
    // Forward sweep
    vector<ll> cprime(n-1,0), dprime(n-1,0);
    // i=0
    ll B0 = B_coeff[0];
    ll C0 = C[0];
    ll D0 = D[0];
    ll invB0 = powmod_func(B0, MOD-2, MOD);
    cprime[0] = C0 * invB0 % MOD;
    dprime[0] = D0 * invB0 % MOD;
    // i=1 to n-2
    for(int i=1;i<n-1;i++){
        ll Ai = A[i];
        ll Bi = B_coeff[i];
        ll Ci = C[i];
        ll Di = D[i];
        // temp = B[i] - A[i] * cprime[i-1}
        ll temp = (Bi + MOD - (Ai * cprime[i-1] % MOD)) % MOD;
        if(temp ==0){
            // No solution, but per problem constraints, it's always solvable
            // To avoid division by zero, set E=0 (though it shouldn't happen)
            cprime[i] =0;
            dprime[i] =0;
            continue;
        }
        ll inv_temp = powmod_func(temp, MOD-2, MOD);
        cprime[i] = (Ci * inv_temp) % MOD;
        dprime[i] = ((Di + MOD - (Ai * dprime[i-1] % MOD)) % MOD * inv_temp) % MOD;
    }
    // Back substitution
    vector<ll> E(n-1,0);
    E[n-2] = dprime[n-2];
    for(int i=n-3;i>=0;i--){
        E[i] = (dprime[i] + MOD - (cprime[i] * E[i+1] % MOD)) % MOD;
    }
    // The answer is E[0]
    cout << E[0];
}

Explanation of Corrections:

  1. Condition Adjustment:

    • Original Issue: The original code incorrectly treated the last variable (corresponding to the second last word) as a normal variable.
    • Correction: The condition if(i < n-2) correctly identifies whether the current word is a normal word or the last word. This ensures that the last word's transition probabilities are handled appropriately.
  2. Handling the Last Variable:

    • For the last variable (word ( n-1 )), there is no ( E[n] ) because ( E[n] = 1 ) is known.
    • The equation for the last variable is adjusted to account for this by setting ( C[i] = 0 ) and adjusting ( D[i] ) accordingly.
  3. Modular Inverse:

    • All divisions are handled using modular inverses to ensure correctness under modulo ( 10^9 + 7 ).
  4. Ensuring Non-Zero Denominators:

    • The code includes a check to avoid division by zero, though according to problem constraints, the system should always be solvable.

Validation with Sample Input:

Let's validate the corrected code with the provided sample:

Input:

3
1 1
1 1

Expected Output:

9

Explanation:

  • Word 1:
    • ( P(1 \rightarrow 2) = \frac{1}{2} )
    • ( P(1 \rightarrow 1) = \frac{1}{2} )
  • Word 2:
    • ( P(2 \rightarrow 3) = \frac{1}{4} )
    • ( P(2 \rightarrow 2) = \frac{1}{2} )
    • ( P(2 \rightarrow 1) = \frac{1}{4} )
  • Word 3:
    • Absorbing state, ( E[3] = 1 )

Solving the system: [ \begin{cases} 0.5 E_1 - 0.5 E_2 = 1 \ -0.25 E_1 + 0.5 E_2 = 1.25 \end{cases} ] Solving these equations yields ( E_1 = 9 ) and ( E_2 = 7 ), which matches the expected output.

Conclusion:

The corrected code now accurately sets up and solves the tridiagonal system representing the Markov chain of Zaoly's speech. By properly handling the last variable and ensuring the correct conditions in the loop, the code now produces the expected results, including for the provided sample input.

全部评论
leetcode早都被橄榄了
点赞 回复 分享
发布于 2024-09-16 23:47 广东

相关推荐

在笔试的大西瓜很矫健:校招数分不用想了,这经历和学历都不够用,大厂更别想,初筛都过不了,说点不好听的小厂数分都进不去(小厂也是假数分),要两个对口实习+3个项目(或者3+2),而且要有含金量才能补一点你的学历劣势。 建议刷实习,社招找数分,校招看运气,能入行业就行,可以运营转数分
点赞 评论 收藏
分享
LZHR:老哥你从投递简历测评完到一面中间隔了多久呀,我这边已经过了五天了仍显示简历筛选中是不是就是挂了
腾讯求职进展汇总
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务