1 条题解

  • 0
    @ 2025-8-24 22:46:50

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar phigos
    **

    搬运于2025-08-24 22:46:50,当前版本为作者最后更新于2023-08-29 10:44:52,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题意简化

    给出 nnlen600len\leq600,仅由 LLPP 构成的字符串,将 LL 看做左括号,PP 看做右括号。

    求任意两个串 aabb 收尾相接后,本质不同的合法括号序列的个数。

    思路

    设左括号价值为 11,右括号价值为 1-1,那么一个序列合法的充要条件是:

    1. 任意前缀的价值和非负

    2. 总价值为 00

    3. 任意后缀的价值和非正

    考虑将 aabb 拼接后的序列的一个子序列分成前缀和后缀,使得前缀在 aa 中,后缀在 bb 中,那么就可以分别在 aabb 中求出价值为 kkk-k 的子序列的方案数。

    dp

    对于 aa 串,设 fronta,j,k,0/1/2front_{a,j,k,0/1/2} 表示 aa 串中,考虑 jj 位,价值和为 kk,且以左括号 // 右括号 // 空串结尾的方案数。

    对于 bb 串,设 backb,j,k,0/1/2back_{b,j,k,0/1/2} 表示 bb 中,考虑 lenj+1len-j+1 位,价值和为 k-k,且以左括号 // 右括号 // 空串开头的方案数。

    初始化

    显然,初始为空串,只有一种情况,即:

    fronta,0,0,2=1front_{a,0,0,2}=1 backb,0,0,2=1back_{b,0,0,2}=1

    考虑如何转移

    若当前位置 jj('('

    fronta,j,k,0fronta,j1,k1,0/1/2front_{a,j,k,0}\gets front_{a,j-1,k-1,0/1/2} backb,j,k,0backb,j+1,k+1,0/1/2back_{b,j,k,0}\gets back_{b,j+1,k+1,0/1/2}

    若当前位置 jj)')'

    fronta,j,k,1fronta,j1,k+1,0/1/2front_{a,j,k,1}\gets front_{a,j-1,k+1,0/1/2} backb,j,k,1backb,j+1,k1,0/1/2back_{b,j,k,1}\gets back_{b,j+1,k-1,0/1/2}

    去重

    但如果直接将 frontfrontbackback 乘起来统计答案会重复

    如图,选择 aapp 左侧加上 bbjj 开头的情况,会和选择 aa 中以 pp 结尾加上 bbjj 右侧的情况重复。

    因此还需要一个数组 ga,j,k,0/1,0/1g_{a,j,k,0/1,0/1} 表示 aa 串中,考虑前 jj 位,价值和为 kkjj 右侧是否有左括号,是否有右括号的方案数。

    l/rl/rjj 右侧剩余的左or右括号数,就有:

    jj 位置为左括号:

    $$g_{a,j,k,l>0,r>0}\gets g_{a,j-1,k,l>0,r>0}+front_{a,j-1,k-1,0/1/2}-front_{a,j-1,k,0} $$

    jj 位置为右括号:

    $$g_{a,j,k,l>0,r>0}\gets g_{a,j-1,k,l>0,r>0}+front_{a,j-1,k+1,0/1/2}-front_{a,j-1,k,1} $$

    像这样,只要 aa 串后面没有 bb 串开头的括号,就不会出现上面的重复情况。

    统计答案

    设答案为 ansans

    bb 串以左括号开头,那么 aa 的末尾不能有左括号; 若 bb 串以右括号开头,那么 aa 的末尾不能有右括号; 若 bb 串为空串,那么 aa 没有限制。

    $$ans\gets (g_{a,n,k,0,0}+g_{a,n,k,0,1})\times back_{b,1,k,0} $$$$ans\gets (g_{a,n,k,0,0}+g_{a,n,k,1,0})\times back_{b,1,k,1} $$$$ans\gets (g_{a,n,k,0,0}+g_{a,n,k,0,1}+g_{a,n,k,1,0}+g_{a,n,k,1,1})\times back_{b,1,k,2} $$

    空间优化

    不难发现,三个 dpdp 数组都要开到 n3n^3,喜提MLE。

    但是,对于 jj 这一维,我们每次转移都只用到了前一位的结果,并且统计答案只用到 j=nj=n,因此可以通过调整循环的方向压掉 jj 这一维。

    时间复杂度为 O(n3)O(n^3),可以通过本题。

    记得取模!!!

    代码

    #include<bits/stdc++.h>
    #define int long long
    #define inf (1ll<<60)
    using namespace std;
    const int N=605,mod=1e9+7;
    int n,front[N][N][3],back[N][N][3],g[N][N][2][2];
    char s[N];
    signed main(){
    	cin>>n;
    	for(int i=1;i<=n;i++){
    		cin>>(s+1);
    		int num=strlen(s+1);
    		int l=0,r=0;
    		for(int j=1;j<=num;j++) s[j]=='L'?l++:r++;//j右侧左/右括号的个数
    		front[i][0][2]=1;
    		back[i][0][2]=1;
    		g[i][0][(bool)l][(bool)r]=1;
    		for(int j=1;j<=num;j++){//正序处理前缀
    			if(s[j]=='L'){l--;
    				for(int k=600;k>=1;k--){
    					(g[i][k][(bool)l][(bool)r]+=front[i][k-1][0]+front[i][k-1][1]+front[i][k-1][2]-front[i][k][0]+mod)%=mod;
    					(front[i][k][0]=front[i][k-1][0]+front[i][k-1][1]+front[i][k-1][2])%=mod;
    				}
    			}else{r--;
    				for(int k=0;k<600;k++){
    					(g[i][k][(bool)l][(bool)r]+=front[i][k+1][0]+front[i][k+1][1]+front[i][k+1][2]-front[i][k][1]+mod)%=mod;
    					(front[i][k][1]=front[i][k+1][0]+front[i][k+1][1]+front[i][k+1][2])%=mod;
    				}
    			}
    		}
    		for(int j=num;j>=1;j--){//倒序处理后缀
    			if(s[j]=='L')
    				for(int k=0;k<600;k++)
    					(back[i][k][0]=back[i][k+1][0]+back[i][k+1][1]+back[i][k+1][2])%=mod;
    			else
    				for(int k=600;k>=1;k--)
    					(back[i][k][1]=back[i][k-1][0]+back[i][k-1][1]+back[i][k-1][2])%=mod;
    		}
    	}
    	for(int i=1;i<=n;i++){//枚举a串
    		for(int j=1;j<=n;j++){//枚举b串
    			int ans=mod-1;
    			for(int k=0;k<=600;k++){
    				(ans+=(g[i][k][0][0]+g[i][k][0][1])*back[j][k][0]%mod)%=mod;
    				(ans+=(g[i][k][0][0]+g[i][k][1][0])*back[j][k][1]%mod)%=mod;
    				(ans+=(g[i][k][0][0]+g[i][k][0][1]+g[i][k][1][0]+g[i][k][1][1])*back[j][k][2]%mod)%=mod;
    			}
    			cout<<ans<<' ';
    		}
    		putchar('\n');
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    8685
    时间
    9000ms
    内存
    512MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者