• 2019牛客暑期多校训练营(第五场)- G subsequence 1


    题目链接:https://ac.nowcoder.com/acm/contest/885/G

    题意:给定字符串s,t,求s中满足字典序大于t的子序列的个数。

    思路:组合数学+dp。当子序列长度大于m时很简单,利用初始化的组合数即可。当子序列长度等于m时类似于数位dp的处理办法,我们用dp[pos][num]表示处理到s中的第pos位时已经选择num个数的可能个数。

       那么当s[pos]>t[num+1]时:

        如果选择s[i]:dp[pos][num]=(dp[pos][num]+C[n-pos][m-num-1])%MOD;

        如果不选:dp[pos][num]=(dp[pos][num]+dfs(pos+1,num))%MOD;

       当num!=m-1&&s[pos]==t[num+1]时(num!=m-1是因为避免相等的情况,相等时只能不选):

        如果选择s[i]:dp[pos][num]=(dp[pos][num]+dfs(pos+1,num+1))%MOD;

        如果不选:dp[pos][num]=(dp[pos][num]+dfs(pos+1,num))%MOD;

       当s[pos]<t[num+1]:

        只能不选:dp[pos][num]=(dp[pos][num]+dfs(pos+1,num))%MOD;

    AC代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
     
    typedef long long LL;
    const int MOD=998244353;
    const int maxn=3005;
     
    int T,n,m;
    char s[maxn],t[maxn];
    LL ans,C[maxn][maxn],dp[maxn][maxn];
     
    void init(){
        for(int i = 0; i < maxn;++i){
            C[i][0] = C[i][i] = 1;
            for(int j = 1; j < i;++j){
                C[i][j] = C[i-1][j] + C[i-1][j-1];
                C[i][j] %= MOD;
            }
        }
    }
     
    LL dfs(int pos,int num){
        if(num==m) return 1;
        if(pos>n) return 0;
        if(dp[pos][num]!=-1) return dp[pos][num];
        LL tmp=0;
        if(s[pos]>t[num+1])
            tmp=(tmp+C[n-pos][m-num-1])%MOD;
        else if(num!=m-1&&s[pos]==t[num+1])
            tmp=(tmp+dfs(pos+1,num+1))%MOD;
        if(n-pos>=m-num)
            tmp=(tmp+dfs(pos+1,num))%MOD;
        return dp[pos][num]=tmp;
    }  
     
    int main(){
        init();
        scanf("%d",&T);
        while(T--){
            ans=0;
            scanf("%d%d",&n,&m);
            scanf("%s",s+1);
            scanf("%s",t+1);
            for(int i=0;i<=n+1;++i)
                for(int j=0;j<=m;++j)
                    dp[i][j]=-1;
            ans=(ans+dfs(1,0));
            for(int i=m+1;i<=n;++i)
                for(int j=1;j<=n-i+1;++j)
                    if(s[j]!='0')
                        ans=(ans+C[n-j][i-1])%MOD;
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Spring源码解析-AutowiredAnnotationBeanPostProcessor
    Spring源码解析-基于注解依赖注入
    Spring源码解析-事件
    Spring源码解析-AOP简单分析
    Spring源码解析-实例化bean对象
    Spring源码解析-配置文件的加载
    linux 条件判断式
    Assembly.LoadFrom加载程序集类型转换失败解决方法
    autodesk fbx sdk sample里面的工程无法调试解决方法
    Unity ---WidgetsUI CreateTileView Demo
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11284065.html
Copyright © 2020-2023  润新知