More than 2019 cattle off summer school camp (fifth) G - subsequeue 1 (a title I'm really not a problem)


layout: POST
title: more than 2019 cattle off summer school camp (fifth) G - subsequeue 1 (a title I'm really not a problem)
author: "luowentaoaa"
Cataog: to true
Tags:
MathJax: to true
- ACM-ICPC


The meaning of problems

Give you two strings of digits \ (S \) , \ (T \) length \ (1E3 \) , you ask how many value S is greater than the string T subsequences;

Thinking

First, a game is determined at the time \ (N ^ 2 \) the DP complexity, but did not want to think of two or three hours how transfer, various configurations \ (dp [i] [j ] \) meaning. But without success.

After the game we found that we have used the number of combinations. It found that two types of questions are used to discuss issues to do. This time it Woon Dawu.

T larger than the original string can be divided into two categories do not have a few blind transfer.

Solution of this problem so quickly thought of, if it is larger than the case, then as long as the first character is not 0, then a few strings behind the casually taken on the line.

Greater than the end of the case the next step is equal. If they are equal then certainly have to consider is the \ (S \) which as a starting point to construct the sequence string. The starting point and the string S, the next point where the transfer. These can all be DP. So we determined the basic state, we must first determine the location to which the current structure of the S series. At the same time the position for which the position of the T string, so that we can begin the transfer.

#include<bits/stdc++.h>
using namespace std;
const int maxn=4e3+50;
typedef long long ll;
const ll mod=998244353;
ll dp[maxn][maxn];
ll C[maxn][maxn];
void add(ll &a,ll b){
    a+=b;
    if(a>=mod)a-=mod;
}
char s[maxn],t[maxn];
int main(){
    std::ios::sync_with_stdio(false);
    int T;
    C[0][0]=1;
    for(int i=1;i<=3000;i++){
        for(int j=0;j<=i;j++){
            if(j==0||j==i)C[i][j]=1;
            else add(C[i][j],C[i-1][j-1]+C[i-1][j]);
        }
    }
    cin>>T;
    while(T--){
        int n,m;
        cin>>n>>m;
        cin>>s+1>>t+1;
        for(int i=0;i<=n+10;i++){
            for(int j=0;j<=m+10;j++)dp[i][j]=0;
        }
        ll ans=0;
        for(int i=1;i<=n;i++){
            if(s[i]=='0')continue;
            for(int j=m;j<=n;j++){
                add(ans,C[n-i][j]);
            }
        }
        ///dp[i][j]= 从后往前到当前S串第j的字符位置匹配到T串的第I个字符并且大于的个数
        for(int i=m;i;i--){
            for(int j=n;j;j--){
                dp[j][i]=dp[j+1][i];  ///因为包括了没有第j个字符的情况,所以如果第j+1个字符符合条件也可以
                if(t[i]==s[j])add(dp[j][i],dp[j+1][i+1]);
                /// 如果两个字符相同 那么答案就是少取这第J个字符同时还大于的数量
                if(t[i]<s[j])add(dp[j][i],C[n-j][m-i]);
                ///如果大于  那么答案就是后面的几个随便取几个就行了。
            }
        }
        cout<<(ans+dp[1][1])%mod<<endl;
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/luowentao/p/11286260.html