組合せ論
$ I $の場所に現在の列挙を仮定
$($の前に$ I $:$を$
$ $ $ $ Iの後に$ B $)
$ $ C:$?$ $ I $の前に
$ D $:$ I $ $ $の後に?
そして、現在位置が貢献に答えるために
$$ \和{+ I \ leqslant B + J} {\ tbinom {C} {I} \ tbinom {D} {J}} $$
i、jは、私は$ $を埋める表し$($、$ J $番目の$で塗りつぶし)$
この式は、私が$この場所に答えるために、現在の$($寄与を計算することと等価であり、括弧の最終回答の対の数を表し、$ +、非常に巧妙です
その後、簡素化を検討
$$ = \ sum_ {+ I \ leqslant B + D - J} {\ tbinom {C} {I} \ tbinom {D} {D - J}} $$
$$ = \ sum_ {X = 0} ^ {B + D - } {\ tbinom {C + D}、{X}} $$
$ C + D $ 2つしか値があるので、前処理することができます
複雑$ O(n)と$
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 const int型の P = 998244353 ; int型{)(メイン ストリングS。 cinを >> 秒; INT、N = s.size()。 ベクター < INT > INV(N + 1)、facinv(N + 1)、FAC(N + 1 )。 FAC [ 0 ] = INV [ 1 ] = facinv [ 0 ] = 1 ; 以下のために(INT iが= 1 ; I <= N; ++ i)が{ もし(!I = 1 ){ INV [I] = 1LL *(P - P / I)* INV [P%I]%のP。 } facinv [I] = 1LL * facinv [I - 1 ] * INV [I]%のP。 [i]は、FAC = 1LL * FAC [I - 1 ] * I%のP。 } int型 = 0、B = 0、C = 0、D = 0 ; 用(自動車E:S){ 場合(E == ' )' ){ ++ B。 } もし、(E == '?' ){ ++ D。 } } マップ < int型、ベクトル< INT >> DP。 オートC = [b](整数 nは、INT M){ 場合(N <M)戻り 0 ; もし(dp.find(N)=!dp.end()){ 戻りDP [n]は[M]。 } オート&TMP = DP [n]は、 int型の合計= 0 ; tmp.resize(N + 1 )。 ために(INT iが= 0 ; <I = N; ++ I){ 和 + = 1LL * FAC [N] * facinv [I]%のP * facinv [N - I]%のP。 合計%= P。 TMP [I] = 合計。 } 戻りTMP [M]。 }。 自動計算値 = [b](int型、INT B、INT C、INT {D) INT X =分(B + D - 、C + D)を、 もし(x < 0)戻り 0 ; リターン C(C +D、X)。 }。 int型 ANS = 0 ; 用(INTは iは= 0 ; I <N ++ {i)が あれば(S [I] == ' (' ){ ++ ; } もし、(S [I] == ' )' ){ - B ; } もし、(S [I] == ' ?' ){ ++ 、C。 - D; } もし、(S [I] == ' (' ){ 年間 + = CALC(A、B、C、D)。 年間%= P; } もし、(S [I] == ' ?' ){ ++ 。 - C; 年間 + = CALC(A、B、C、D)。 年間%= P; - ; ++ 、C; } } Coutの <<年<< ' \ n個' ; リターン 0 ; }