括号字符串期望


给一个仅由‘(’,')','?'组成的字符串,字符串长度为n,‘?’可以变换成'(',')'。变换后的相邻括号对的数学期望为E,求E*2^n(结果必为正整数,可证明),结果对10^9+7取模。仅当s[i]='('且s[i+1]=')'时,才构成一个相邻括号对。

相邻括号对定义
仅当s[i]='('且s[i+1]=')'时,才构成一个相邻括号对。
输入格式
·第一行:整数n (1 ≤ n ≤ 10^6)
·第二行:字符串s
输出格式
一个整数,表示E×2^n mod 10^9+7

字符串 (???),长度为 5

这里有 3 个 '?',所以有 2^3 = 8 种可能的替换方式。

枚举所有替换方式

  1. ( ( ( ( ) → ((()))  1

  2. ( ( ( ) ) → ((())  1

  3. ( ( ) ( ) → (()()   2

  4. ( ( ) ) ) → (()))   1

  5. ( ) ( ( ) → ()(()  2

  6. ( ) ( ) ) → ()())   2

  7. ( ) ) ( ) → ())(()  2

  8. ( ) ) ) ) → ())))  1

计算相邻括号对总数

将所有情况的相邻括号对相加:1 + 1 + 2 + 1 + 2 + 2 + 2 + 1 = 12。

计算期望 E

期望 E 是相邻括号对的总和除以替换方式的数量:E = 12 / 8 = 1.5

计算 E * 2^n

n = 52^5 = 32。所以 E * 2^n = 1.5 * 32 = 48

取模

48 mod (10^9 + 7) = 48(因为 48 < 10^9 + 7)。

image

 

#include <iostream>
#include <string>
#include <vector>

using namespace std;

const int MOD = 1e9 + 7;

int main() {
    int n;
    string s;
    cin >> n >> s;
    
    vector<int> pow2(n + 1);
    pow2[0] = 1;
    for (int i = 1; i <= n; ++i) {
        pow2[i] = (pow2[i - 1] * 2) % MOD;
    }
    
    int total = 0;
    for (int i = 0; i < n - 1; ++i) {
        int m = 0;
        bool possible = false;
        if ((s[i] == '(' || s[i] == '?') && (s[i + 1] == ')' || s[i + 1] == '?')) {
            possible = true;
            m = (s[i] == '?') + (s[i + 1] == '?');
        }
        if (possible) {
            total = (total + pow2[n - m]) % MOD;
        }
    }
    
    cout << total << endl;
    
    return 0;
}

 

posted @ 2025-08-04 22:47  最近饭吃的很多  阅读(35)  评论(0)    收藏  举报