zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    [原]Android 开发第一步
    [转]使用Android-Studio 开发Android 程序
    [转]VS2010 常用插件
    [转]FluentData
    BUUCTF-[HCTF 2018]WarmUp
    2019.11.11读书笔记
    2019.11.9读书笔记
    记录一道神仙CTF-wtf.sh-150
    SDOI2018 一轮培训划水祭
    [SHOI2009]会场预约
  • 原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/9866599.html
Copyright © 2011-2022 走看看