AFO

牛客网NOIP赛前集训营-普及组(第一场)

普及组。。。

T1/T2
T3
链接:C

小A有一个只包含左右括号的字符串S。但他觉得这个字符串不够美观,因为它不是一个合法的括号串。一个合法的括号串是这样定义的:

  1. ()是合法的括号串

  2. 若A是合法的括号串,则(A)则是合法的括号串

  3. 若A,B是合法的括号串,则AB也是合法的括号串。

小A现在希望删掉S中若干个字符,使得剩下的字符串是一个合法的括号串。小A想知道有多少不同的方案。两个方案是不同的,当且仅当他们删除的位置不同。比如当S是(()时,有两种方案。分别是删掉第一个位置,或是删掉第二个位置。


dp,\(f[i][j]\)表示前\(i\)个位置未配平的左括号的个数为\(j\)的方案数,转移

\[f[i][j]=\left\{\begin{matrix} &s[i]='('\ \ | f[i][j]=f[i-1][j-1]+f[i-1][j]& \\ &s[i]='\ )'\ \ | f[i][j]=f[i-1][j]+f[i-1][j+1] & \end{matrix}\right.\]

标程是滚动数组,然鹅并不需要啊并不需要,直接压成一维数组即可,每次转移时左移或右移一位。

#include<iostream>
#include<cstdio>

using namespace std;

int i,m,n,j,k,a[1001][1001],b[10001],f[10001];
char c;
int main()
{
	scanf("%d",&n);
	for(i=1;i<=n;i++) 
	{
		cin>>c;
		if(c==')') b[i]=1;
	}
	f[0]=1;
	for(i=1;i<=n;i++)
	if(b[i]) for(j=1;j<=k;j++) f[j-1]+=f[j];
	else {
		k+=1; 
		for(j=k;j>=0;j--) f[j+1]+=f[j];
	}
	printf("%d",f[0]-1);
}

T4
链接:D

小A有n个长度都是L的字符串。这些字符串只包含前8个小写字符,'a'~'h'。但这些字符串非常的混乱,它们几乎长得互不相同。小A想通过一些规则,让它们长得尽可能相同。小A现在有K次机会,他可以每次机会,可以选择一对字符x,y,让x,y变成等价的字符(注意这里x,y和字符'x', 'y'不是一样的,只是个代号)。注意,等价关系是有传递性的。比如小A让'a'和'b'等价, 'b'和'c'等价,那么'a'和'c'等价。

对于两个长度字符串P,Q是等价的,当且仅当对于每一位,P的字符和Q的字符都是等价的。

小A希望你告诉他,要怎么利用好这K次机会(当然可以不用完),使得尽可能多对字符串是等价的。注意每对字符串只能算一次。


普及组考斯特林数...我可能真的只适合去玩泥巴

当k大于7时我们可以把图连成一棵树也就是全部匹配。
穷举匹配情况时间爆炸,所以枚举的是联通情况是为(8,8-K),在可以接受的范围内。
由于字符串长度很大,check答案还是会超时,所以Hash掉每个字母的出现情况一起判断即可


posted @ 2019-10-12 16:06  ZUTTER☮  阅读(170)  评论(0编辑  收藏  举报