1. 程式人生 > 其它 >2021牛客多校5 D Double Strings

2021牛客多校5 D Double Strings

傳送門

那麼這個題的題意非常的抽象,在做題之前我們不妨仔細地,認真地,多讀幾遍題,然後我們可以發現題意大概是 :

在 兩個字串中 ,分別選出長度相等地子序列,使得從第二個中選出地子序列的字典序大小大於第一個

那麼我們就可以將這兩個子序列分段,分為

“一段相同的字首 + 一個不同的字元 (第一個比第二個小) + 任意長度相同的字尾”

這樣就將問題分解了。
於是我們需要求的就是

1: A,B兩個字串所具有的相同的字首的個數
\(dp[i][j]\)表示第一個字串前i個位置和第二個字串前j個位置所具有的相同的子序列,這裡空字串也算一個子序列,因此得到初始狀態和轉移條件:

    dp[i][0]=dp[0][j]=1;
    dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];
    if a[i]==b[j] : dp[i][j]+=dp[i-1][j-1];

2:任意長度相同的字尾的個數

對於當前位置 i,j ,不妨令i > j,則選取任意字尾的方案數為

\(\sum_{x=0}^{n-i}C(n-i,x)*C(m-j,x)\)
\(=\sum_{x=0}^{n-i}C(n-i,n-i-x)*C(m-j,x)\)
\(=C(n-i + m-j,n-i)\)

程式碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include <unordered_map>
#include<vector>
#include<set>
#include<cmath>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rpe(i,a,b) for(int i=a;i>=b;--i)
#define pts putchar('\n')
#define ptc putchar(' ')
#define pb push_back
typedef long long ll;
typedef pair<int,int>P;
typedef unsigned long long ull;
const int inf=0x7f7f7f7f;
const ll linf=1e18;
const int maxn=5e3+9;
const int maxm=2e5+9;
const double PI=3.1415926;
const double eps=1e-5;
const ll mod=1e9+7;
const int base=131;
const int N=1e6;
char A[maxn],B[maxn];
int dp[maxn][maxn];
int n,m;
ll fac[maxn*2],inv[maxn*2];
ll qpow(ll a,ll b){
	ll sum=1;
	while(b){
		if(b&1) sum=sum*a%mod;
		a=a*a%mod;b>>=1;
	}
	return sum;;
}
void pre(){
	fac[0]=1;
	rep(i,1,10000) fac[i]=1LL*fac[i-1]*i%mod;
	inv[10000]=qpow(fac[10000],mod-2);
	rpe(i,9999,0) inv[i]=1LL*inv[i+1]*(i+1)%mod;
}
ll C(int x,int y){
	return fac[x]*inv[y]%mod*inv[x-y]%mod;
}

int main(){
	scanf("%s %s",A+1,B+1);
	n=strlen(A+1);m=strlen(B+1);
	rep(i,0,n) dp[i][0]=1;
	rep(i,0,m) dp[0][i]=1;
	ll ans=0;pre();
	rep(i,1,n){
		rep(j,1,m){
			dp[i][j]=(dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1])%mod;
			if(A[i]==B[j]) (dp[i][j]+=dp[i-1][j-1])%=mod;
			else if(A[i]<B[j]){
				ans=(ans+ 1LL * dp[i-1][j-1] * C(n - i   + m-j,n-i) %mod)%mod;;
			} 
		}
	}
	printf("%lld",(ans+mod)%mod);
    return 0;
}