继续打卡 Codeforces Round #604 (Div. 2) F题

容斥 dp
题意:给出()序列和?,?可以变成‘(’或者‘)’,问如果是贪心匹配可以操作任意次去掉任意括号,求所有情况深度的和。
分情况讨论。dp[i][j]表示i~j这段所有情况的深度和。
1.左括号==')‘,那么dp[i][j]=dp[i+1][j]
2.右括号=='(',那么dp[i][j]=dp[i][j-1]
3.1,2情况同时发生 ,dp[i][j]-=dp[i+1][j-1](容斥)
4.左括号=='?',继续分两种情况,?变成')',或者'(',变成‘)‘情况同理和1一样。变成了'('的话,同情况7。
5.右括号 =='?',和上面4类似。
6.4,5情况同时发生且我们假定左括号 ==')'右括号 =='(',这时和情况三一样。
7.左括号==’(‘and右括号==')’,dp[i][j]=dp[i+1][j-1]+1;
8.4,5情况同时发生,且变成了情况7,dp[i][j]=dp[i+1][j-1]+1*2^k。(表示2^k情况加1)
综上所述,一共可以合并成4种情况。详见代码。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
    char ch = getchar(); ll x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int mod = 998244353;
const int N = 2e3 + 10;
ll dp[N][N];
char s[N];
ll pw[N];
ll sum[N];
void init(int n)
{
    pw[0] = 1;
    upd(i, 1, 2000)
        pw[i] = (pw[i - 1] * 1ll*2)%mod;
    upd(i, 1, n)
    {
        if (s[i] == '?')sum[i] = sum[i - 1] + 1;
        else sum[i] = sum[i - 1];
    }
}
int main()
{
    scanf("%s", s+1);
    int n = strlen(s+1);
    init(n);
    up(i, 1, n)
    {
        for (int j = 1; j+i<=n; j++)
        {
            int r = j + i;
            if (s[j] != '(')dp[j][r] = (dp[j][r] + dp[j + 1][r]) % mod;
            if (s[r] != ')')dp[j][r] = (dp[j][r] + dp[j][r - 1]) % mod;
            if (s[j] != '('&&s[r] != ')')dp[j][r] = (dp[j][r] - dp[j + 1][r - 1] + mod) % mod;
            if (s[j] != ')'&&s[r] != '(')dp[j][r] = (dp[j][r] + dp[j + 1][r - 1] + pw[sum[r-1] - sum[j]]) % mod;
        //  cout << dp[j][r] << endl;
        }
    }
    printf("%lld\n", dp[1][n]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LORDXX/p/12045766.html