牛客多校第五场G

subsequence 1

只要处理长度等于t的.

转移方程没想出来QAQ

$dp(i,j,0)$代表到$s[i]$为止有多少个前缀序列与$t[0\cdots j]$相同

所以有$dp(i,j,0)=dp(i-1,j,0)+s[i]==t[j]?dp(i-1,j-1,0):0;$

$dp(i,j,1)$代表到$s[i]$为止有多少个子序列大于$t[0\cdots j]$

故有$dp(i,j,1)=dp(i-1,j,1)+(s[i]>t[j])*dp(i,j-1,0)+(j>0)*dp(i-1,j-1,0)$

#include<bits/stdc++.h>
using namespace std;
char s[3050],t[3050];
typedef long long ll;
ll dp[3005][3005][2];
ll C[3003][3003];
ll mod=998244353;
void init()
{
    for(int i=0;i<3001;i++){
        C[i][i]=1;
        C[i][0]=1;
    }
    for(int i=1;i<3001;i++){
        for(int j=i+1;j<3001;j++){
            C[j][i]=(C[j-1][i-1]+C[j-1][i])%mod;
        }
    }
}
int main()
{
    int T;
    int n,m;
    ll ans;
    init();
    scanf("%d",&T);
    while(T--){
        ans=0;
        scanf("%d%d",&m,&n);
        scanf("%s",s);
        scanf("%s",t);
       for(int i=0;i<=max(m,n);i++)
        dp[i][0][1]=dp[i][0][0]=1;
       // for(int i=0;i<=n;i++)dp[0][i]=1;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){

                dp[i+1][j+1][0]=((dp[i][j][0])*(s[i]==t[j])+dp[i][j+1][0])%mod;
                dp[i+1][j+1][1]=(dp[i][j+1][1]+(s[i]>t[j])*dp[i][j][0]+(j>0)*dp[i][j][1])%mod;
             //   cout<<dp[i+1][j+1][1]<<' ';
            }
           // cout<<'\n';
           // cout<<i<<" "<<ans<<'\n';
        }
        ans=dp[m][n][1];
        //cout<<ans<<'\n';
        for(int k=n+1;k<=m;k++)
        for(int i=1;i+k-1<=m;i++){
            if(s[i-1]!='0')
            ans=(ans+C[m-i][k-1])%mod;
        }
        cout<<ans<<'\n';

    }
}

猜你喜欢

转载自www.cnblogs.com/liulex/p/11291499.html