$$ \newcommand{\seq}[2]{{#1}_{1},{#1}_{2},\cdots,{#1}_{#2}} \newcommand{\num}[1]{1,2,\cdots,#1} \newcommand{\stra}[2]{\begin{bmatrix}#1 \\ #2\end{bmatrix}} \newcommand{\strb}[2]{\begin{Bmatrix}#1 \\ #2\end{Bmatrix}} \newcommand{\dw}[1]{\underline{#1}} \newcommand{\up}[1]{\overline{#1}} $$

XJOI 3877 红蓝字符串

题意

给你一个偶数长度的字符串,你想要给每一个字符标记成蓝色或者红色,使得红色的字符序列等于蓝色的字符序列,一共有多少种方法可以做这件事

输入格式

输入一行包含一个字符串\(S, (2≤|S|≤40)\)
字符串的每个字符为'o'或者'x'

输出格式

输出一个整数

样例输入&输出

样例1

oxox

2

样例2

oooxxx

0

样例3

xoxxox

4

样例4

xo

0

样例5

ooooxoox

8

样例6

ooxxoxox

8

样例7

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

137846528820

分析

本题就是要寻找长度为 \(\frac{|S|}{2}\)\(S\) 的子序列 \(S_1\) 的个数,使 \(S\) 的另一个子序列 \(S_2\)\(S_1\) 相等,且 \(S_2\)\(S_1\) 互斥,即对于任意\(S_1[i],S_2[j],i≠j\)

我们能确定 \(S_1\) 的长度(即\(\frac{|S|}{2}\)),以及 \(S_1\) 中'o'和'x'的个数,于是想到爆搜穷举每一个可能的 \(S_1\) ,最多搜\(C^{20}_{10}=184756\)次。对于每一个可能的 \(S_1\) ,我们用\(O(n^2)\)的dp去检验它的方案数。设 \(dp[i][j]\) 表示枚举到第 \(i\) 位,其中有 \(j\) 位与 \(S_1\) 匹配的方案数,则

\[if(dp[i-1][j-1]存在且b[j]==a[i])dp[i][j]+=dp[i-1][j-1] \]

\[if(dp[i-1][j]存在且b[i-j]==a[i])dp[i][j]+=dp[i-1][j] \]

初始化\(dp[0][0]=1\)

最终答案为\(dp[n][n/2]\)

总时间复杂度为\(O(C^{n}_{n/2}* n^2)≈295609600\),卡卡常能过

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 45
using namespace std;
char s[maxn];
bool a[maxn],b[maxn];
int n,n1,n0;
long long ans,dp[maxn][maxn];
long long check(){
	for(int i=0;i<=n;i++){
		for(int j=0;j<=(n>>1);j++){
			dp[i][j]=0;
		}
	}
	dp[0][0]=1;
	for(int i=1;i<=n;i++){
		for(int j=0;j<=min(i,(n>>1));j++){
			if(j&&dp[i-1][j-1]&&b[j]==a[i])dp[i][j]+=dp[i-1][j-1];
			if(j<i&&dp[i-1][j]&&b[i-j]==a[i])dp[i][j]+=dp[i-1][j];
		}
	}
	return dp[n][n>>1];
}
void dfs(int step){
	if(step>(n>>1)){
		ans+=check();
		return;
	}
	if(n1){
		n1--;
		b[step]=1;
		dfs(step+1);
		n1++;
	}
	if(n0){
		n0--;
		b[step]=0;
		dfs(step+1);
		n0++;
	}
}
int main(){
	scanf("%s",s);
	n=strlen(s);
	for(int i=1;i<=n;i++){
		a[i]=(s[i-1]=='x');
		n1+=a[i],n0+=!a[i];
	}
	n1>>=1,n0>>=1;
	dfs(1);
	printf("%lld",ans);
	return 0;
}
posted @ 2018-10-28 18:58  chc_1234567890  阅读(332)  评论(0编辑  收藏  举报