topcoder srm 686 div1 -3

1、给出只包含‘(‘,‘)‘,‘[‘,‘]‘的字符串$s$,删除一些字符,使得剩下的是合法的括号。有多少种删除方法? $|s|\leq 40$

思路:左括号和右括号较少的一种不会大于20。假设左括号少。设$f[i][mask][k]$表示处理了前$i$个字符,其中留下的字符以$k$开头($k=0$表示‘(‘,$k=1$表示‘[‘),且所有留下的字符状态为$mask$,($mask$的最高位为1,其他位为0表示另一种括号,否则表示跟最高位相同的符号)。

#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
using namespace std;

long long f[2][1<<20][2];

class BracketSequenceDiv1
{
public:
	long long count(string s)
	{
	    const int n=(int)s.size();
	    int L=0,R=0;
	    for(int i=0;i<n;++i)
        {
            if(s[i]==‘(‘||s[i]==‘[‘) ++L;
            else ++R;
        }
        if(L>R)
        {
            reverse(s.begin(),s.end());
            for(int i=0;i<n;++i)
            {
                if(s[i]==‘(‘) s[i]=‘)‘;
                else if(s[i]==‘)‘) s[i]=‘(‘;
                else if(s[i]==‘[‘) s[i]=‘]‘;
                else s[i]=‘[‘;
            }
            swap(L,R);
        }

        int pre=0,cur=1;
        memset(f[pre],0,sizeof(f[pre]));
        f[0][0][0]=1;
        for(int i=1;i<=n;++i)
        {
            char c=s[i-1];
            memset(f[cur],0,sizeof(f[cur]));

            for(int j=0;j<(1<<L);++j) for(int k=0;k<2;++k) if(f[pre][j][k])
            {
                long long p=f[pre][j][k];
                f[cur][j][k]+=p;
                if(c==‘(‘)
                {
                    if(j==0)      f[cur][1][0]+=p;
                    else f[cur][j<<1|(!k)][k]+=p;
                }
                else if(c==‘[‘)
                {
                    if(j==0) f[cur][1][1]+=p;
                    else f[cur][j<<1|k][k]+=p;
                }
                else if(c==‘)‘)
                {
                    if(j!=0&&(k^(j&1))) f[cur][j>>1][k]+=p;
                }
                else
                {
                    if(j!=0&&(0==(k^(j&1)))) f[cur][j>>1][k]+=p;
                }
            }

            pre^=1;
            cur^=1;
        }

        return f[pre][0][0]+f[pre][0][1]-1;
	}
};

  

时间: 2024-12-29 15:51:08

topcoder srm 686 div1 -3的相关文章

TOPCODER SAM 686 div1 300

// TOPCODER SAM 686 div1 300 Problem Statement 带有小中括号的括号序列,问可以去掉多少子串,使得剩下的非空串是合法的. Constraints 字符串长度不超过 40. Examples // ans[i] = count(s[i]) string s[] = {"()[]", "())", "()()", "([)]", "())[]][]([]()]]()]]]&qu

Topcoder SRM 643 Div1 250&lt;peter_pan&gt;

Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*......*pn,我们假设p0,p1,...,pn是单调不降的,那么v里存储的是下标为偶数 的N的质因数p0,p2,p4,...,p(2k).现在要求写一个程序,返回一个vector<long long>ans; ans里存储的是p0,p1,p2,...,pn. Limits Time Limit(m

TOPCODER SRM 686 div2 1000

// TOPCODER SRM 686 div2 1000 Problem Statement 给出一个至多长 100 的字符串,仅包含 ( 和 ),问其中有多少个不重复的,合法的括号子序列. 子序列可以不连续:合法即括号序列的合法:答案模 1,000,000,007. Examples "(())(" Returns: 2 Correct non-empty bracket subsequences are "()" and "(())". &

Topcoder SRM 648 Div1 250

Problem 给一个长度为N的"AB"字符串S,S只含有两种字符'A' 或 'B',设pair(i,j)(0=<i<j<N)表示一对 i,j 使得S[i]='A',S[j]='B'.现给定一个K,求字符串S,使得pair(i,j)的个数恰好为K.若不存在,则返回空串. Limits Time Limit(ms): 2000 Memory Limit(MB): 256 N: [2, 50] K: [0 , N*(N-1)/2 ] Solution 若K>(N/2

Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串

Problem Statement      The Happy Letter game is played as follows: At the beginning, several players enter the field. Each player has a lowercase English letter on their back. The game is played in turns. In each turn, you select two players with dif

topcoder srm 738 div1 FindThePerfectTriangle(枚举)

Problem Statement      You are given the ints perimeter and area. Your task is to find a triangle with the following properties: The coordinates of each vertex are integers between 0 and 3000, inclusive. The perimeter of the triangle must be exactly

Topcoder SRM 603 div1题解

昨天刚打了一场codeforces...困死了...不过赶在睡前终于做完了- 话说这好像是我第一次做250-500-1000的标配耶--- Easy(250pts): 题目大意:有一棵树,一共n个节点,每个节点都有一个权值,两人A和B分别进行操作,由A先手,每人可以选择一条边,将它删掉得到两个联通块.游戏不断进行下去,最后只剩下一个节点.A希望最后的节点权值尽可能大,B希望尽可能小,求这个最后的值.数据保证n<=50. 这道题真的是博弈好题啊-(感觉放到ACM很合适啊) 我们考虑第一次A会如何选

topcoder srm 320 div1

problem1 link 两个数字后面都有阶乘符号,可以抵消. import java.util.*; import java.math.*; import static java.lang.Math.*; public class ExtraordinarilyLarge { public String compare(String x, String y) { boolean both=false; while(x.endsWith("!")&&y.endsWit

topcoder srm 712 div1 -23

1.给定两个长度为$n$的数组$A,B$.有两种操作可以作用于数组$A$.第一种,将每个元素左侧的相邻数字加到其上:第二种,将每个元素右侧的相邻数字加到其上.0的左侧是$n-1$,$n-1$的右侧是0.比如1,2,3,4执行第一种操作后是5,3,5,7.给出一个不超过100的操作序列使得$A$变成$B$.$n \leq 50$. 思路:将$a_{0},a_{1},...,a_{n-1}$看做$a_{0}x^{0}+a_{1}x^{1}+...+a_{n-1}x^{n-1}$.那么第一种操作相当于