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;
}

posted @ 2021-08-01 15:32  Mr_cold  阅读(52)  评论(0编辑  收藏  举报