zoukankan      html  css  js  c++  java
  • JZOJ6343. 【NOIP2019模拟2019.9.7】Medium Counting

    Description

    在这里插入图片描述
    1n50,1L201leq n leq 50,1leq L leq 20

    Solution

    • 简单的计数,但是我的考虑方向并不正确,设的状态也不好做,导致正解其实并不难,但是我在考场上没有做出来。
    • 既然已经给定了顺序,那么一段满足条件一定是前几个字符完全一样,后面再区分开来。
    • 如果我们按照从后往前的顺序做,就很好转移,有点类似区间DP。
    • f[i][l][r][c]f[i][l][r][c]表示llrr的后i位已经确定并且能区分开来,第i位最大的字符为c
    • 枚举一个rr',让r+1~r’的第i位都为字符c’,转移到f[i][l][r][c]f[i][l][r'][c']
    • 要满足c<c’,所以用一个前缀和优化一下就好了。
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define maxn 55
    #define maxl 22
    #define ll long long 
    #define mo 990804011
    using namespace std;
    
    int n,i,j,k,L,l,r,len[maxn];
    char ch;
    int s[maxn][maxl];
    ll f[maxl][maxn][maxn][27];
    
    int main(){
    	freopen("b.in","r",stdin);
    	freopen("b.out","w",stdout);
    	scanf("%d",&n);
    	for(i=1;i<=n;i++){
    		for(ch=getchar();(ch<'a'||ch>'z')&&ch!='?';ch=getchar());
    		for(;(ch>='a'&&ch<='z')||ch=='?';ch=getchar()) {
    			++len[i];
    			if (ch=='?') s[i][len[i]]=-1; else 
    				s[i][len[i]]=ch-'a'+1;
    		}
    		L=max(L,len[i]);
    	}
    	for(i=1;i<=n;i++) f[L+1][i][i][26]=1;
    	for(k=L;k>=1;k--){
    		for(l=1;l<=n;l++) if (s[l][k]==0) f[k][l][l][0]=1;
    		for(l=1;l<=n;l++) for(r=l;r<=n;r++) {
    			for(j=1;j<=26;j++){
    				f[k][l][r][j]=f[k][l][r][j-1];
    				for(i=r;i>l&&(s[i][k]==-1||s[i][k]==j);i--) 
    					f[k][l][r][j]+=f[k][l][i-1][j-1]*f[k+1][i][r][26]%mo;
    				if (i==l&&(s[i][k]==-1||s[i][k]==j)) 
    					f[k][l][r][j]+=f[k+1][l][r][26];
    				f[k][l][r][j]%=mo;
    			}
    		}
    	}
    	printf("%lld",f[1][1][n][26]);
    }
    
    
  • 相关阅读:
    洛谷P1261 服务器储存信息问题
    洛谷P2110 欢总喊楼记
    洛谷P2482 [SDOI2010]猪国杀
    洛谷P2756 飞行员配对方案问题
    洛谷P2763 试题库问题
    洛谷P2774 方格取数问题
    Huffman编码
    SA后缀数组
    KMP
    LCA
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/13090970.html
Copyright © 2011-2022 走看看